Packages

Simple queue implementation for webhooks and event sources.

Retired package: Deprecated

Current section

Files

Jump to
pollin lib backends memory workers callback_worker.ex
Raw

lib/backends/memory/workers/callback_worker.ex

defmodule Pollin.Backend.Memory.CallbackWorker do
@moduledoc """
Worker for callbacks
"""
use GenServer
use Pollin.CallbackInterface
alias Pollin.Backend.Memory.EndpointWorker
@doc false
def start_link(id) when is_atom(id),
do: GenServer.start_link(__MODULE__, [], name: id)
@doc false
def init(_opts),
do: {:ok, []}
## Private API
@doc false
def handle_cast({:push, id, cb, secret}, state) do
endpoint = EndpointWorker.find("#{id}")
if endpoint && endpoint.secret == secret do
if endpoint.ttl > 0 do
Process.send_after(self, {:delete, cb.id}, endpoint.ttl)
end
{:noreply, List.insert_at(state, -1, {cb.id, cb})}
else
{:noreply, state}
end
end
@doc false
def handle_cast({:reset}, _state),
do: {:noreply, []}
@doc false
def handle_cast({:delete, key}, state) do
new_state = List.keydelete(state, key, 0)
{:noreply, new_state}
end
@doc false
def handle_cast({:update_status, key, status}, state) do
case List.keyfind(state, key, 0) do
{key, cb} ->
cb = Map.put(cb, :status, status)
{:noreply, List.keyreplace(state, key, 0, {key, cb})}
nil -> {:noreply, state}
end
end
@doc false
def handle_call({:pop}, _from, [{_key, cb} | state]),
do: {:reply, cb, state}
@doc false
def handle_call({:pop, key}, _from, state) when is_binary(key) do
case List.keytake(state, key, 0) do
{{_key, cb}, new_state} -> {:reply, cb, new_state}
nil -> {:reply, nil, state}
end
end
@doc false
def handle_call({:pop, %{status: status, offset: offset, limit: limit}}, _from, state) do
items =
state
|> Enum.group_by(fn {_key, cb} -> cb.status end)
|> Map.get(status, [])
|> Enum.slice(offset, limit)
{:reply, items |> Enum.map(fn {_key, cb} -> cb end), state -- items}
end
@doc false
def handle_call({:pop, %{offset: offset, limit: limit}}, _from, state) do
items =
state
|> Enum.slice(offset, limit)
{:reply, items |> Enum.map(fn {_key, cb} -> cb end), state -- items}
end
@doc false
def handle_call({:fetch}, _from, [{_key, cb} | _state] = state),
do: {:reply, cb, state}
@doc false
def handle_call({:fetch, key}, _from, state) when is_binary(key) do
case List.keyfind(state, key, 0) do
{_key, cb} -> {:reply, cb, state}
nil -> {:reply, nil, state}
end
end
@doc false
def handle_call({:fetch, %{status: status, offset: offset, limit: limit}}, _from, state) do
items =
state
|> Enum.group_by(fn {_key, cb} -> cb.status end)
|> Map.get(status, [])
|> Enum.slice(offset, limit)
|> Enum.map(fn {_key, cb} -> cb end)
{:reply, items, state}
end
@doc false
def handle_call({:fetch, %{offset: offset, limit: limit}}, _from, state) do
items =
state
|> Enum.slice(offset, limit)
|> Enum.map(fn {_key, cb} -> cb end)
{:reply, items, state}
end
@doc false
def handle_call({:fetch_reverse, %{status: status, offset: offset, limit: limit}}, _from, state) do
items =
state
|> Enum.reverse
|> Enum.group_by(fn {_key, cb} -> cb.status end)
|> Map.get(status, [])
|> Enum.slice(offset, limit)
|> Enum.map(fn {_key, cb} -> cb end)
{:reply, items, state}
end
@doc false
def handle_call({:fetch_reverse, %{offset: offset, limit: limit}}, _from, state) do
items =
state
|> Enum.reverse
|> Enum.slice(offset, limit)
|> Enum.map(fn {_key, cb} -> cb end)
{:reply, items, state}
end
@doc false
def handle_call({:count}, _from, state),
do: {:reply, Enum.count(state), state}
@doc false
def handle_call({:count, %{status: status}}, _from, state) do
count =
state
|> Enum.group_by(fn {_key, cb} -> cb.status end)
|> Map.get(status, [])
|> Enum.count
{:reply, count, state}
end
@doc false
def handle_call({:dump}, _from, state) do
items =
state
|> Enum.map(fn {_key, cb} -> cb end)
{:reply, items, state}
end
end