Packages

A distributed, compacting, multidimensional, telemetry-powered time series datastore

Current section

Files

Jump to
oban_met lib oban met application.ex
Raw

lib/oban/met/application.ex

defmodule Oban.Met.Application do
@moduledoc false
use Application
alias Oban.{Config, Registry}
require Logger
@main_sup Oban.Met.Supervisor
@task_sup Oban.Met.TaskSupervisor
@handler_id :oban_met_handler
@impl Application
def start(_type, _args) do
:telemetry.attach(@handler_id, [:oban, :supervisor, :init], &__MODULE__.init_metrics/4, [])
children = [
{Task.Supervisor, name: @task_sup},
{Task, &boot_metrics/0}
]
Supervisor.start_link(children, strategy: :one_for_one, name: @main_sup)
end
@impl Application
def prep_stop(state) do
:telemetry.detach(@handler_id)
state
end
@doc false
def init_metrics(_event, _measure, %{conf: conf}, _conf) do
start_metrics(conf)
end
@doc false
def boot_metrics do
guard = {:andalso, {:is_map, :"$1"}, {:==, {:map_get, :__struct__, :"$1"}, Config}}
[{{:_, :_, :"$1"}, [guard], [:"$1"]}]
|> Registry.select()
|> Enum.each(&start_metrics/1)
end
defp start_metrics(conf) do
opts = Application.get_all_env(:oban_met)
if opts[:auto_start] and conf.testing in opts[:auto_testing_modes] do
spec = Oban.Met.child_spec(conf: conf)
case Supervisor.start_child(@main_sup, spec) do
{:ok, _pid} ->
Task.Supervisor.start_child(@task_sup, fn -> watch_oban(spec, conf) end)
:ok
{:error, {:already_started, _pid}} ->
:ok
{:error, {error, _stack}} ->
Logger.error("Unable to start Oban.Met supervisor: #{inspect(error)}")
end
end
end
defp watch_oban(%{id: child_id}, conf) do
ref =
conf.name
|> Oban.whereis()
|> Process.monitor()
receive do
{:DOWN, ^ref, :process, _pid, _reason} ->
Process.demonitor(ref, [:flush])
with :ok <- Supervisor.terminate_child(@main_sup, child_id) do
Supervisor.delete_child(@main_sup, child_id)
end
end
end
end