token_server/lib/token_server.ex
2024-06-28 18:51:49 +09:00

64 lines
1.7 KiB
Elixir

defmodule TokenServer do
use GenServer
require Logger
alias TokenServer.ApiClient
# Server
@impl GenServer
@spec init(any()) :: {:ok, DateTime.t()}
def init(_) do
:ets.new(:token_store, [:named_table, read_concurrency: true])
expires_at = get_and_store_token()
{:ok, expires_at}
end
@impl GenServer
@spec handle_info(any(), DateTime.t()) :: {:noreply, DateTime.t()}
def handle_info(:refresh, _expires_at) do
expires_at = get_and_store_token()
{:noreply, expires_at}
end
def handle_info(msg, expires_at) do
Logger.info("Received unknown message: #{inspect(msg)}")
{:noreply, expires_at}
end
@impl GenServer
@spec handle_call(:force_refresh, GenServer.from(), DateTime.t()) :: {:reply, :ok, DateTime.t()}
def handle_call(:force_refresh, _from, _expires_at) do
expires_at = get_and_store_token()
{:reply, :ok, expires_at}
end
defp get_and_store_token() do
{token, expires_at} = ApiClient.get_token()
:ets.insert(:token_store, {:token, token})
next_refresh = DateTime.add(expires_at, -5, :minute)
ms_to_refresh = DateTime.diff(next_refresh, DateTime.utc_now(), :millisecond)
Process.send_after(self(), :refresh, ms_to_refresh)
expires_at
end
# Client
@doc """
A function to start this GenServer as part of the supervision tree, registered with the
name of the module.
"""
@spec start_link(any()) :: GenServer.on_start()
def start_link(_) do
GenServer.start_link(__MODULE__, nil, name: __MODULE__)
end
@spec get() :: String.t()
def get(), do: :ets.lookup_element(:token_store, :token, 2)
@spec force_refresh() :: :ok
def force_refresh() do
GenServer.call(__MODULE__, :force_refresh)
end
end