Skip to content

Instantly share code, notes, and snippets.

@mprymek
Created September 28, 2015 08:39
Show Gist options
  • Save mprymek/0a8f175d6c9201a81c62 to your computer and use it in GitHub Desktop.
Save mprymek/0a8f175d6c9201a81c62 to your computer and use it in GitHub Desktop.
defmodule TokenHolder do
require Logger
def start_link(user,passwd) do
Agent.start_link(fn ->
tok_time = get_token user, passwd
{user,passwd,tok_time}
end, name: __MODULE__)
end
# refresh the token if older that three seconds
@max_age 3000000
def token do
Agent.get_and_update(__MODULE__, fn state={user,passwd,{token,retrieved}} ->
Logger.info "[PID=#{inspect self}=TokenHolder] Retrieving token"
now = :os.timestamp
age = :timer.now_diff(now, retrieved)
if(age < @max_age) do
Logger.info "Token age is #{age} - we can still use it"
# return old token and old state
{token,state}
else
Logger.info "Token age is #{age} - we must get a new one"
# retrieve new token, return it and return changed state
tok_time = {token,_} = get_token user, passwd
{token,{user,passwd,tok_time}}
end
end)
end
defp get_token(_user,_passwd) do
token = :random.uniform 100
{token,:os.timestamp}
end
end
defmodule MyAPI do
@moduledoc "Simulates API access"
require Logger
@doc "Simulates accessing one API endpoint"
def users do
token = TokenHolder.token
Logger.info "[PID=#{inspect self}] We are accessing API using token #{token}"
:timer.sleep 1000
Logger.info "[PID=#{inspect self}] We got answer."
["John","George","Martin"]
end
end
defmodule Main do
require Logger
def main do
# start logger
:ok = Application.ensure_started :logger
# start TokenHolder
{:ok,_} = TokenHolder.start_link "user", "secret"
# these two requests will be done in parallel
master = self
spawn_link(fn ->
users = MyAPI.users
Logger.info "users = #{inspect users}"
send master, :done
end)
spawn_link(fn ->
users = MyAPI.users
Logger.info "users = #{inspect users}"
send master, :done
end)
# wait for the requests to be finished
receive do :done -> :ok end
receive do :done -> :ok end
Logger.info "We are waiting now to simulate token expiration..."
:timer.sleep 5000
# these two requests will be done in parallel with a new token
spawn_link(fn ->
users = MyAPI.users
Logger.info "users = #{inspect users}"
end)
spawn_link(fn ->
users = MyAPI.users
Logger.info "users = #{inspect users}"
end)
end
end
Main.main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment