defmodule Fmcsa.Company.Server do require Logger use GenServer @name __MODULE__ @registry_name :company_registry @ten_seconds 10000 @one_day 834_000 def child_spec(company) do %{ id: __MODULE__, start: {__MODULE__, :start_link, [company]}, restart: :transient, type: :worker } end defstruct name: nil, profile: nil, last_update: nil def start_link( data) do {name, url} = data name = via_tuple(name) GenServer.start_link(__MODULE__, [data], name: name) end def fetch_profile(data) do {name, url} = data try do GenServer.call(via_tuple(name), {:fetch, url}) catch :exit, _ -> {:error, "company not loaded"} end end def show_profile(data) do {name, url} = data try do GenServer.call(via_tuple(name), :show_state) catch :exit, _ -> {:error, "company not loaded"} end end def handle_call(:show_state, _from, state) do {:reply, state, state} end defp via_tuple(data) do {:via, Registry, {@registry_name, data}} end def init([args]) do {name, url} = args Process.send_after(self(), {:sync, url}, @ten_seconds) {:ok, %__MODULE__{}} end def handle_call({:fetch, url}, _from, state) do profile = Fmcsa.fetch_company_profile(url) updated_state = %__MODULE__{state | profile: profile} updated_state = %{updated_state | last_update: DateTime.utc_now()} {:reply, profile, updated_state} end def handle_info({:sync, url}, state) do profile = Fmcsa.fetch_company_profile(url) updated_state = %__MODULE__{state | profile: profile} updated_state = %{updated_state | last_update: DateTime.utc_now()} Process.send_after(self(), {:sync, url}, @one_day) :telemetry.execute( [:fmcsa, :request, :sync], %{time_in_milliseconds: 0}, %{ id: state.name, last_update: state.last_update } ) {:noreply, updated_state} end end