Current section
Files
Jump to
Current section
Files
lib/execution.ex
defmodule Firefighter.Execution do
@type execution :: %__MODULE__{}
@callback start(data :: map) :: execution
@callback record(exec :: execution, data :: map) :: execution
@callback record_many(exec :: execution, name :: binary, data :: list | map) :: execution
@callback push(exec :: execution, pid :: any) :: execution
@callback hose(pid :: any, data :: map) :: execution
defstruct [
:event_uuid,
:event_time,
:elapsed,
data: %{}
]
def start(ids) do
%__MODULE__{
event_uuid: uuid(),
event_time: current_time_in_milliseconds(),
data: ids
}
end
def record(%__MODULE__{data: data} = execution, ids) do
%{execution | data: Map.merge(data, ids)}
end
def record_many(%__MODULE__{} = execution, name, list_of_ids) when is_list(list_of_ids) do
list_of_ids
|> Enum.reduce(execution, fn ids, end_execution ->
record_many(end_execution, name, ids)
end)
end
def record_many(%__MODULE__{data: data} = execution, name, ids) when is_map(ids) do
many = data[name] || []
data = Map.put(data, name, [ids | many])
%{execution | data: data}
end
def push(%__MODULE__{} = execution, id) when not is_pid(id) do
case Process.whereis(id) do
nil -> raise ArgumentError, "No process found for id #{id}"
pid -> push(execution, pid)
end
end
def push(%__MODULE__{event_time: event_time} = execution, pid) when is_pid(pid) do
elapsed = current_time_in_milliseconds() - event_time
execution = %{execution | elapsed: elapsed / 1_000}
record = to_record(execution)
firefighter().push(pid, record)
execution
end
def hose(id, ids) do
start(ids) |> push(id)
end
defp to_record(%__MODULE__{event_uuid: event_uuid, elapsed: elapsed, data: data}) do
record =
%{event_uuid: event_uuid, elapsed: elapsed}
|> Map.merge(data)
json().encode!(record)
end
defp uuid, do: UUID.uuid4()
defp current_time_in_milliseconds, do: System.monotonic_time(:millisecond)
defp firefighter, do: Application.get_env(:firefighter, :firefighter, Firefighter)
defp json, do: Application.get_env(:firefighter, :json, Jason)
end