# `Wardrik.Listener`

Follows agents' events into your app.

Each event comes with the cursor just past it. Save the cursor with your work, and the listener
picks up from it after a restart.

    defmodule MyApp.Runs do
      use Wardrik.Listener, wardrik: MyApp.AgentRuntime, types: ["wardrik.run.completed"]

      @impl true
      def handle(%Wardrik.Event{} = event, listener) do
        MyApp.Repo.transaction(fn ->
          MyApp.Repo.insert!(MyApp.Run.from(event), on_conflict: :nothing)
          MyApp.Cursors.put!("runs", listener.cursor)
        end)

        :ok
      end

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

Start it after Wardrik in your supervision tree, or have Wardrik start it:

    Wardrik.start_link(name: MyApp.AgentRuntime, listeners: [MyApp.Runs])

## Options

Give options to `use`, or as it starts. Your own options are kept alongside them.

  * `:wardrik` - required. The module to follow, as `MyApp.AgentRuntime`.
  * `:resources` - patterns of the agents to follow. Every agent unless set.
  * `:types` - event types to follow. Every type unless set.
  * `:after` - the cursor to start after, if you don't define `c:cursor/1`.

Without a cursor, it starts with events written after it starts.

## Delivery

Each event is delivered at least once. Save the cursor in the same transaction as your work,
and drop repeats by the event's `id`. If `c:handle/2` raises or returns anything but `:ok`, the
listener restarts and calls `c:cursor/1` again.

# `t`

```elixir
@type t() :: %Wardrik.Listener{
  cursor: String.t() | nil,
  options: keyword(),
  wardrik: atom()
}
```

The listener: the `:wardrik` it follows, the cursor past the current event, and its options.

# `cursor`

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

Returns the cursor to start after, or `nil` to start with new events. Defaults to `:after`.

# `handle`

```elixir
@callback handle(Wardrik.Event.t(), t()) :: :ok
```

Handles `event`. Returns `:ok` when done.

# `start_link`

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

Starts `module` as a listener. See the module docs for `opts`.

---

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