Current section
Files
Jump to
Current section
Files
lib/google_ads/token_cache.ex
defmodule GoogleAds.TokenCache do
@moduledoc """
Cache instance for Google Ads tokens.
"""
use GenServer
@cache_table :google_ads_tokens
@type prismatic_ref :: String.t()
@spec start_link(any()) :: {:ok, pid()} | {:error, any()}
def start_link(_opts) do
GenServer.start_link(__MODULE__, nil, name: __MODULE__)
end
@impl GenServer
def init(_opts) do
@cache_table = :ets.new(@cache_table, [:set, :public, :named_table])
{:ok, %{}}
end
@spec insert(prismatic_ref(), GoogleAds.Token.t()) :: :ok
@spec insert(prismatic_ref(), GoogleAds.Token.t(), DateTime.t()) :: :ok
def insert(prismatic_ref, %GoogleAds.Token{} = token, now \\ DateTime.utc_now()) do
GenServer.call(__MODULE__, {:insert, prismatic_ref, token, now})
end
@spec get(prismatic_ref()) :: GoogleAds.Token.t() | nil
def get(prismatic_ref) do
case :ets.lookup(@cache_table, prismatic_ref) do
[{^prismatic_ref, %GoogleAds.Token{} = token}] -> token
_any -> nil
end
end
@doc false
@spec flush() :: any()
def flush, do: :ets.delete_all_objects(@cache_table)
@impl GenServer
def handle_call({:insert, prismatic_ref, %GoogleAds.Token{} = token, now}, _from, state) do
{:ok, expires_at, 0} = DateTime.from_iso8601(token.expires_at)
expires_in_seconds = DateTime.diff(expires_at, now, :second)
true = :ets.insert(@cache_table, {prismatic_ref, token})
Process.send_after(self(), {:remove, prismatic_ref}, :timer.seconds(expires_in_seconds))
{:reply, :ok, state}
end
@impl GenServer
def handle_info({:remove, prismatic_ref}, state) do
true = :ets.delete(@cache_table, prismatic_ref)
{:noreply, state}
end
end