Skip to content

Commit

Permalink
🛂 Handle TokenWorker dying 💀
Browse files Browse the repository at this point in the history
  • Loading branch information
RustySnek committed May 16, 2024
1 parent d1ab900 commit 1e0647f
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 65 deletions.
5 changes: 3 additions & 2 deletions lib/elixirus/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ defmodule Elixirus.Application do
children = [
ElixirusWeb.Telemetry,
Elixirus.Healthcheck.HealthSupervisor,
Supervisor.child_spec({TokenWorker, [:token_storage, :set, :public]},
id: TokenWorker
Supervisor.child_spec({TokenWorker, :ets.new(:token_storage, [:set, :public])},
id: TokenWorker,
restart: :permanent
),
{DNSCluster, query: Application.get_env(:elixirus, :dns_cluster_query) || :ignore},
{Phoenix.PubSub, name: Elixirus.PubSub},
Expand Down
129 changes: 66 additions & 63 deletions lib/elixirus/token_worker.ex
Original file line number Diff line number Diff line change
@@ -1,84 +1,87 @@
defmodule Elixirus.TokenWorker do
use GenServer
alias Timex
import Elixirus.PythonWrapper
use GenServer
require Logger
alias Timex
import Elixirus.PythonWrapper

def start_link(args) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end
def start_link(args) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end

def init([table_name | opts]) do
table = :ets.new(table_name, opts)
{:ok, table, {:continue, :init_status}}
end
def init(table) do
Logger.warning("restarted token worker")
{:ok, table, {:continue, :init_status}}
end

def handle_call({:add_token, username, token, ttl}, _from, table) do
:ets.insert(table, {username, token, ttl, DateTime.now!("Europe/Warsaw")})
{:reply, :ok, table}
end
def handle_call({:add_token, username, token, ttl}, _from, table) do
:ets.insert(table, {username, token, ttl, DateTime.now!("Europe/Warsaw")})
{:reply, :ok, table}
end

def handle_call({:extend_lifetime, token}, _from, table) do
case :ets.match(table, {:"$1", token, :"$2", :_}) do
[] ->
:ok
def handle_call({:extend_lifetime, token}, _from, table) do
case :ets.match(table, {:"$1", token, :"$2", :_}) do
[] ->
:ok

[[name, ttl] | _] ->
unless(name == nil,
do: :ets.insert(table, {name, token, ttl, DateTime.now!("Europe/Warsaw")})
)
end
[[name, ttl] | _] ->
unless(name == nil,
do: :ets.insert(table, {name, token, ttl, DateTime.now!("Europe/Warsaw")})
)
end

{:reply, :ok, table}
end
{:reply, :ok, table}
end

def handle_call({:extend_lifetime, token, ttl}, _from, table) do
case :ets.match(table, {:"$1", token, :_, :_}) do
[] ->
:ok
def handle_call({:extend_lifetime, token, ttl}, _from, table) do
case :ets.match(table, {:"$1", token, :_, :_}) do
[] ->
:ok

[[name] | _] ->
unless(name == nil,
do: :ets.insert(table, {name, token, ttl, DateTime.now!("Europe/Warsaw")})
)
end
[[name] | _] ->
unless(name == nil,
do: :ets.insert(table, {name, token, ttl, DateTime.now!("Europe/Warsaw")})
)
end

{:reply, :ok, table}
end
{:reply, :ok, table}
end

def handle_cast({:remove_token, username, token}, table) do
[{_username, lookup_token, _ttl, _last_update} | _] = :ets.lookup(table, username)
def handle_cast({:remove_token, username, token}, table) do
[{_username, lookup_token, _ttl, _last_update} | _] = :ets.lookup(table, username)

if lookup_token == token do
:ets.delete(table, username)
end
if lookup_token == token do
:ets.delete(table, username)
end

{:noreply, table}
end
{:noreply, table}
end

def handle_continue(:init_status, table), do: execute_token_refresh(table)
def handle_continue(:init_status, table), do: execute_token_refresh(table)

def handle_info(:refresh, table), do: execute_token_refresh(table)
def handle_info(:refresh, table), do: execute_token_refresh(table)

defp execute_token_refresh(table) do
:ets.tab2list(table)
|> Task.async_stream(fn token -> refresh_token(table, token) end)
|> Enum.to_list()
defp execute_token_refresh(table) do
:ets.tab2list(table)
|> Task.async_stream(fn token -> refresh_token(table, token) end, timeout: 30 * 1000)
|> Enum.to_list()

Process.send_after(self(), :refresh, 30 * 60 * 1000)
{:noreply, table}
end
Process.send_after(self(), :refresh, 15 * 60 * 1000)
{:noreply, table}
end

defp refresh_token(table, {username, token, ttl, last_update}) do
now = DateTime.now!("Europe/Warsaw")
defp refresh_token(table, {username, token, ttl, last_update}) do
now = DateTime.now!("Europe/Warsaw")

if now <= Timex.shift(last_update, hours: ttl) do case python(:helpers, :refresh_oauth, [token]) do :ok ->
:ets.insert(table, {username, token, ttl, now})
if now <= Timex.shift(last_update, hours: ttl) do
case python(:helpers, :refresh_oauth, [token]) do
:ok ->
:ets.insert(table, {username, token, ttl, now})

{:error, __message} ->
:ets.delete(table, username)
end
else
:ets.delete(table, username)
end
end
{:error, __message} ->
:ets.delete(table, username)
end
else
:ets.delete(table, username)
end
end
end

0 comments on commit 1e0647f

Please sign in to comment.