Hello!
I am working on a LiveBook project to wrangle some data.
I have a token management module adapted from StackOverflow:
# TOKEN MANAGER
defmodule TokenHolder do
def start_link() do
Agent.start_link(fn ->
{token, tok_time} = get_token()
{token, tok_time}
end, name: __MODULE__)
end
# refresh the token if older that one hour
@max_age 60*60*1000000
def token do
Agent.get_and_update(__MODULE__, fn {token,retrieved} ->
now = :os.timestamp
if(:timer.now_diff(now, retrieved) < @max_age) do
# return old token and old state
{token,retrieved}
else
# retrieve new token, return it and return changed state
get_token()
end
end)
end
defp get_token() do
token_url = "https://login.solutionsbytext.com/connect/token"
client_id = "ABC123"
client_secret = System.get_env("LB_CLIENT_SECRET")
token_data = [
client_id: client_id,
client_secret: client_secret,
grant_type: "client_credentials"
]
resp = Req.post!(token_url, form: token_data)
# IO.inspect(resp, label: "TOKEN RESP")
token = resp.body["access_token"]
{token,:os.timestamp}
end
end
I run this:
I can run token = TokenHolder.token
in a cell and get a token.
I have another module:
defmodule GetSubscriberStatus do
def new(phone) do
brand_id = "n4t4333"
token = TokenHolder.token
...
It fails with:
Evaluation process terminated - an exception was raised:
** (FunctionClauseError) no function clause matching in anonymous fn/1 in TokenHolder.token/0
I’m confused about why I can get a token outside this module but not within it–and maybe just confused in general. I obviously don’t understand the “matching function clause” error. The {token, retrieved}
bit should be there after {:ok,_} = TokenHolder.start_link()
, shouldn’t it?
I’m picturing it as each time I call token = TokenHolder.token
in GetSubscriberStatus
, TokenHolder
checks that my token is valid. If there is no token, or the existing token is expired, it fetches a new one and returns that. In this way, I should be able to gracefully handle expired tokens when needed.
I tried before to run token = TokenHolder.token
in its own cell, then passing token
when I call GetSubscriberStatus
, like this:
|> Flow.map(&GetSubscriberStatus.new(&1, token))
but it failed with an expired token.
Please help me understand.
If there is a better approach in LiveBook, I’d happily adopt it.
Thank you in advance!