# `Snodo.Subscription.Source`
[🔗](https://github.com/joshrotenberg/snodo/blob/v0.4.1/lib/snodo/subscription/source.ex#L1)

Application-owned event source boundary for `subscriptions/listen`.

Sources open a lightweight handle, pull one event at a time, and close that
handle when the request is cancelled, disconnected, completed, or fails.
`next/2` may block; the framework always invokes it in a dedicated worker and
never requests another event until the previous event has been written.
`open/3` must acknowledge only a subset of its requested filter. `close/3`
should return promptly and release any application resources associated with
a blocked pull. The framework calls `close/3` at most once for a successfully
opened handle, including when the serving process exits during handoff or
shutdown.

`next/2` may be called for a handle after `close/3` has closed it. The owner
stops the worker while the guard closes the handle, so a worker
that is being stopped can still pull, and a source that serializes calls
through one process, such as a `GenServer`, can receive that pull after the
close. `next/2` should return `:closed` for a closed handle rather than raise
or crash the source process.

# `close_reason`

```elixir
@type close_reason() ::
  :cancelled | :disconnected | :complete | {:error, term()} | term()
```

# `config`

```elixir
@type config() :: module() | {module(), term()} | Snodo.Subscription.Source.Config.t()
```

# `close`

```elixir
@callback close(handle :: term(), close_reason(), options :: term()) :: :ok | term()
```

# `next`

```elixir
@callback next(handle :: term(), options :: term()) ::
  {:ok, Snodo.Subscription.Event.t()} | :closed | {:error, term()}
```

# `open`

```elixir
@callback open(requested_filter :: map(), Snodo.Context.t(), options :: term()) ::
  {:ok, accepted_filter :: map(), handle :: term()}
  | {:error, Snodo.Error.t() | term()}
```

---

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