live_beats/lib/live_beats.ex

74 lines
2.1 KiB
Elixir
Raw Normal View History

2021-09-02 18:00:57 +00:00
defmodule LiveBeats do
2021-11-15 17:42:12 +00:00
@moduledoc """
The main interface for shared functionality.
"""
require Logger
2021-09-02 18:00:57 +00:00
2021-11-15 17:42:12 +00:00
@doc """
Attaches a modules to another for listening of events.
Events are executed in the caller's process. Accepts
the `:to` option which a tuple of the form: {ContextModule, StructModule}
You attached to conctext modules on a struct-by-struct basis for granular
events. The struct module passed must implement a valid struct or an error
is raised.
Events that executed are sent to a `handle_execute/2`, callback, which the
source module and executed event as arguments.
## Examples
defmodule MyModule do
def handle_execute({Accounts, %Accounts.Events.UpdateUpdated{user: user}}) do
IO.inspect({:user_updated, user})
end
end
iex> LiveBeats.attach(MyModule, to: {Accounts, Accounts.Events.UserUpdated})
:ok
iex> LiveBeats.execute(Accounts, %Accounts.Events.UserUpdated{user: new_user})
"""
def attach(target_mod, opts) when is_atom(target_mod) do
{src_mod, struct_mod} = Keyword.fetch!(opts, :to)
_ = struct_mod.__struct__
:ok =
:telemetry.attach(target_mod, [src_mod, struct_mod], &__MODULE__.handle_execute/4, %{
target: target_mod
})
end
2021-11-15 17:42:12 +00:00
@doc """
Executes an event from the context module with an event struct.
Events are exected *in the caller's process*, for every attached listener.
## Examples
iex> LiveBeats.attach(MyModule, to: {Accounts, Accounts.Events.UserUpdated})
:ok
iex> LiveBeats.execute(Accounts, %Accounts.Events.UserUpdated{user: new_user})
"""
def execute(src_mod, event_struct) when is_struct(event_struct) do
:telemetry.execute([src_mod, event_struct.__struct__], event_struct, %{})
end
@doc false
def handle_execute([src_mod, event_mod], %event_mod{} = event_struct, _meta, %{target: target}) do
try do
target.handle_execute({src_mod, event_struct})
catch
kind, err ->
Logger.error """
executing {#{inspect(src_mod)}, #{inspect(event_mod)}} failed with #{inspect(kind)}
#{inspect(err)}
"""
end
end
2021-09-02 18:00:57 +00:00
end