WardrikEvents.Listener behaviour (wardrik_events v0.1.0-rc.1)

Copy Markdown

Follows agents' events into your app.

A listener hands each event to handle/2, with the cursor past it. Save the cursor with your work, and return it from cursor/1. The listener then carries on from there after a restart.

defmodule MyApp.Runs do
  use WardrikEvents.Listener

  @impl true
  def handle(event, listener) do
    MyApp.Repo.transaction(fn ->
      MyApp.Repo.insert_all("agent_events", [MyApp.Runs.row(event)], on_conflict: :nothing)
      MyApp.Cursors.put!("runs", listener.cursor)
    end)

    :ok
  end

  @impl true
  def cursor(_listener), do: MyApp.Cursors.get("runs")
end

children = [{MyApp.Runs, events: MyApp.Events, types: ["wardrik.run.completed"]}]

Options

  • :events - required. The name of your WardrikEvents.
  • :resources - patterns of the logs to follow. ["*"], every agent, unless set.
  • :types - the event types to take. Every type unless set. A wardrik.events.dropped always comes through.
  • :after - the cursor to start after, if you don't define cursor/1. What's written next unless set.

Your module's own options can sit beside these. They're in the listener's :options.

Delivery

Each event is handed over at least once.

  1. Save the cursor in the same transaction as your work.
  2. If handle/2 raises or returns anything but :ok, the listener restarts.
  3. On restart it calls cursor/1 again, and reads after what it returns.

So drop a repeat by the event's id.

Summary

Types

t()

The listener's events name, the cursor past the event being handled, and its options.

Callbacks

Returns the cursor to read after as the listener starts, or nil for what's written next. Returns :after unless defined.

Handles event. Returns :ok once it's done.

Functions

Returns the child spec that runs module's listener as a permanent Task.

Starts module's listener with opts, linked to the caller.

Types

t()

@type t() :: %WardrikEvents.Listener{
  cursor: String.t() | nil,
  events: atom(),
  options: keyword()
}

The listener's events name, the cursor past the event being handled, and its options.

Callbacks

cursor(t)

@callback cursor(t()) :: String.t() | nil

Returns the cursor to read after as the listener starts, or nil for what's written next. Returns :after unless defined.

handle(t, t)

@callback handle(WardrikEvents.CloudEvent.t(), t()) :: :ok

Handles event. Returns :ok once it's done.

Functions

child_spec(module, opts)

@spec child_spec(module(), keyword()) :: Supervisor.child_spec()

Returns the child spec that runs module's listener as a permanent Task.

start_link(module, opts)

@spec start_link(module(), keyword()) :: {:ok, pid()}

Starts module's listener with opts, linked to the caller.