Packages

SuperWorker is a powerful Elixir library for working with supervisors and background jobs. It provides a much simpler approach than traditional supervisors. This library is currently under development and is unstable, so it is not recommended for production use.

Current section

Files

Jump to
super_worker lib supervisor db db.ex
Raw

lib/supervisor/db/db.ex

defmodule SuperWorker.Supervisor.Db do
@moduledoc false
alias :ets, as: Ets
alias SuperWorker.Supervisor.{Worker, Group, Chain}
require Logger
def init(sup_name) when is_atom(sup_name) do
# TO-DO: move to protect/private for secure
^sup_name =
Ets.new(sup_name, [
:set,
:public,
:named_table,
{:write_concurrency, true},
{:read_concurrency, true}
])
Logger.debug("SuperWorker, Db, created table for supervisor #{inspect(sup_name)}")
sup_name
end
def put_worker(table, ref, worker_id, parent, pid) do
Ets.insert_new(table, {{:ref, ref}, worker_id, parent, pid})
end
def get_worker(table, ref) do
with {:ok, {_, worker_id, parent, pid}} <- lookup(table, {:ref, ref}) do
{:ok, {worker_id, parent, pid}}
end
end
def get_worker_by_id(table, worker_id, parent) do
case Ets.match_object(table, {{:ref, :_}, worker_id, parent, :_}) do
[{{_, ref}, _, _, pid}] -> {:ok, {ref, pid}}
[] -> {:error, :not_found}
end
end
def delete_worker(table, ref) do
Ets.delete(table, {:ref, ref})
end
def delete_worker_by_id(table, worker_id, parent) do
with {:ok, {ref, _}} <- get_worker_by_id(table, worker_id, parent) do
delete_worker(table, ref)
end
end
def get_workers_by_parent(table, parent) do
result =
Ets.match_object(table, {{:ref, :_}, :_, parent, :_})
|> Enum.map(fn {_, worker_id, _, pid} -> {worker_id, pid} end)
{:ok, result}
end
def get_worker_info_by_ref(table, ref) do
with {:ok, {worker_id, parent, _pid}} <- get_worker(table, ref) do
get_worker_info(table, worker_id, parent)
end
end
def put_worker_info(table, %Worker{} = worker_info) do
Ets.insert_new(
table,
{{:worker, worker_info.id, {worker_info.type, worker_info.parent}}, worker_info}
)
end
def get_worker_info(table, worker_id, parent) do
with {:ok, {_, worker_info}} <- lookup(table, {:worker, worker_id, parent}) do
{:ok, worker_info}
end
end
def delete_worker_info(table, worker_id, parent) do
Ets.delete(table, {:worker, worker_id, parent})
end
def get_worker_infos_by_parent(table, parent) do
result =
Ets.match_object(table, {{:worker, :_, parent}, :_})
|> Enum.map(fn {_, worker} -> worker end)
{:ok, result}
end
def get_all_standalone_worker_infos(table) do
result =
Ets.match_object(table, {{:worker, :_, {:standalone, nil}}, :_})
|> Enum.map(fn {_, worker} -> worker end)
{:ok, result}
end
def get_all_workers(table) do
result =
Ets.match_object(table, {{:worker, :_, :_}, :_})
|> Enum.map(fn {_, worker_info} -> worker_info end)
{:ok, result}
end
def put_group(table, %Group{} = group) do
Ets.insert_new(table, {{:group, group.id}, group})
end
def delete_group(table, group_id) do
Ets.delete(table, {:group, group_id})
end
def get_group(table, group_id) do
with {:ok, {_, group}} <- lookup(table, {:group, group_id}) do
{:ok, group}
end
end
def get_all_groups(table) do
groups =
Ets.match_object(table, {{:group, :_}, :_})
|> Enum.map(fn {_, group} -> group end)
{:ok, groups}
end
def put_chain_order(table, worker_id, chain_id, order, pid) do
Ets.insert_new(table, {{:chain_order, chain_id, order}, {worker_id, pid}})
end
def get_chain_order(table, chain_id, order) do
with {:ok, {_, data}} <- lookup(table, {:chain_order, chain_id, order}) do
{:ok, data}
end
end
def delete_chain_order(table, chain_id, order) do
Ets.delete(table, {:chain_order, chain_id, order})
end
def put_chain(table, %Chain{} = chain) do
Ets.insert_new(table, {{:chain, chain.id}, chain})
end
def get_chain(table, chain_id) do
with {:ok, {_, chain}} <- lookup(table, {:chain, chain_id}) do
{:ok, chain}
end
end
def get_all_chains(table) do
chains =
Ets.match_object(table, {{:chain, :_}, :_})
|> Enum.map(fn {_, chain} -> chain end)
{:ok, chains}
end
def delete_chain(table, chain_id) do
Ets.delete(table, {:chain, chain_id})
end
def put_sup_info(table, partition_id, opts) do
Ets.insert_new(table, {{:supervisor, partition_id}, opts})
end
def get_sup_info(table, partition_id) do
with {:ok, {_, opts}} <- lookup(table, {:supervisor, partition_id}) do
{:ok, opts}
end
end
def delete_sup_info(table, partition_id) do
Ets.delete(table, {:supervisor, partition_id})
end
def put_sup_pid(table, partition_id, pid) do
Ets.insert_new(table, {{:supervisor_pid, partition_id}, pid})
end
def get_sup_pid(table, partition_id) do
with {:ok, {_, pid}} <- lookup(table, {:supervisor_pid, partition_id}) do
{:ok, pid}
end
end
def get_all_sup_pids(table) do
result =
Ets.match_object(table, {{:supervisor_pid, :_}, :_})
|> Enum.map(fn {{_, partition_id}, pid} -> {partition_id, pid} end)
{:ok, result}
end
def delete_sup_pid(table, partition_id) do
Ets.delete(table, {:supervisor_pid, partition_id})
end
## private functions ##
defp lookup(table, key) do
case Ets.lookup(table, key) do
[] ->
{:error, :not_found}
[data] ->
{:ok, data}
_ ->
Logger.error("wrong table type for #{inspect(table)}")
{:error, :wrong_table_type}
end
end
end