# `WardrikEvents.Listener`

Follows agents' events into your app.

A listener hands each event to `c:handle/2`, with the cursor past it. Save the cursor with your
work, and return it from `c: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 `c: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 `c:handle/2` raises or returns anything but `:ok`, the listener restarts.
  3. On restart it calls `c:cursor/1` again, and reads after what it returns.

So drop a repeat by the event's `id`.

# `t`

```elixir
@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.

# `cursor`

```elixir
@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`

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

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

# `child_spec`

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

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

# `start_link`

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

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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
