defmodule Together do @moduledoc ~S""" Group actions that can be handled / responded to later together ## What for? - group notifications to be sent in *one* email - cancel the previously queued email if another event happens within a short period (type: debounce) - make heavy operations happen less often, i.e. refresh some global statistics - allow only 1 operation per certain period (type: throttle) - protect some write api - additonally you can choose to use the first value in a period (keep: first) - or the last value in the period (keep: last) ## How to use Start `Together.Supervisor` to use it ### Start with application configs supervisor(Together.Supervisor, []) ### Start with configs passed in supervisor(Together.Supervisor, [workers: ..., store: ...]) See `Together.Supervisor` for full configuration information Make calls to the worker process: Together.process(binary_name, "something_unique", some_func) Together.process(pid, "some_unique_name_or_id", a_function) Together.process(Together.Worker, "id", Module, :func, [arg1, arg2, ...]) """ @registry_name Together.WorkerRegistry @doc ~S""" put in a function under the id to be processed (invoked) later """ @spec process(binary | GenServer.server, term, fun) :: :ok | no_return def process(name, id, func) when is_binary(name) do GenServer.call({:via, Registry, {@registry_name, name}}, {:process, id, func}) end def process(server, id, func) do GenServer.call(server, {:process, id, func}) end @doc ~S""" put in an `mfa` under the id to be processed (applied) later """ @spec process(binary | GenServer.server, term, module, atom, list) :: :ok | no_return def process(name, id, m, f, a) when is_binary(name) do GenServer.call({:via, Registry, {@registry_name, name}}, {:process, id, {m, f, a}}) end def process(server, id, m, f, a) do GenServer.call(server, {:process, id, {m, f, a}}) end @doc ~S""" cancels queued action for the given id """ @spec cancel(binary | GenServer.server, term) :: :ok | :error def cancel(name, id) when is_binary(name) do GenServer.call({:via, Registry, {@registry_name, name}}, {:cancel, id}) end def cancel(server, id) do GenServer.call(server, {:cancel, id}) end end