# `Chronicle.EventSequences.Streams`
[🔗](https://github.com/Cratis/Chronicle.Elixir/blob/main/lib/chronicle/event_sequences/streams.ex#L4)

Closing, reopening and inspecting event streams, and reading event metadata.

Closing a stream scope stops further events being appended inside it. A scope is described by
any of `:event_source_id`, `:event_source_type`, `:event_stream_type` and `:event_stream_id`
(leave a dimension out to leave it unconstrained). Closing events declared with
`Chronicle.Events.EventType.closes_stream/1` close scopes as part of their own append; the
functions here are the operator's tools for the same ends and for looking at the result.

Mirrors the .NET client's closed-stream APIs. All functions accept `:client`, `:namespace`
and `:event_sequence_id` (default `"event-log"`).

# `closed`

```elixir
@spec closed(keyword()) ::
  {:ok, [Chronicle.EventSequences.Streams.ClosedStream.t()]} | {:error, term()}
```

Lists the closed stream scopes, optionally narrowed by `:event_source_id`,
`:event_source_type`, `:event_stream_type` and `:event_stream_id`.

# `complete_scope`

```elixir
@spec complete_scope(keyword()) :: {:ok, non_neg_integer()} | {:error, term()}
```

Closes a stream scope so no further events can be appended inside it.

The scope is described with `:event_source_id`, `:event_source_type`, `:event_stream_type` and
`:event_stream_id`. Pass `:expected_tail_sequence_number` to refuse the closure when the scope's
tail moved since it was read.

Returns `{:ok, sequence_number}` or `{:error, reason}` where reason is one of
`:already_completed`, `:default_stream_cannot_be_completed`, `:empty_scope` or
`:expected_tail_mismatch`.

# `get_metadata`

```elixir
@spec get_metadata([non_neg_integer()], keyword()) ::
  {:ok, [map()]} | {:error, term()}
```

Reads the metadata of events by sequence number: who caused them, when, under which
correlation id, their tags and subject - without their content.

Returns `{:ok, [metadata]}` where each entry is a map with `:sequence_number`, `:event_type_id`,
`:event_source_type`, `:event_source_id`, `:event_stream_type`, `:event_stream_id`, `:occurred`,
`:correlation_id`, `:causation`, `:caused_by` (gains `:on_behalf_of`), `:initiator_type`
(`:unknown | :user | :agent | :system`), `:resolved_caused_by` (a
`Chronicle.EventSequences.ResolvedIdentity`, carrying how the kernel resolved the identity),
`:tags`, `:subject` and `:event_source`.

`sequence_numbers` is de-duplicated before the request is sent. The kernel limits a single
request to 500 locators; above that this returns
`{:error, {:too_many_event_locators, 500}}` without sending one.

# `get_metadata_at`

```elixir
@spec get_metadata_at(non_neg_integer(), keyword()) :: {:ok, map()} | {:error, term()}
```

Reads the metadata of a single event by sequence number. See `get_metadata/2`.

Returns `{:ok, metadata}`, `{:error, :not_found}` when no event exists at that sequence
number, or `{:error, reason}`.

# `reopen_scope`

```elixir
@spec reopen_scope(String.t(), keyword()) :: :ok | {:error, term()}
```

Reopens a stream scope that was closed with `complete_scope/1` (or `EventLog.complete_stream/3`).

A scope closed by a closing event is reopened by appending one of its `reopened_by` events
instead (`{:error, :closed_by_event}`). `reason` is recorded with the reopening. Returns `:ok`
or `{:error, :not_completed | :closed_by_event | term}`.

# `scope_completed?`

```elixir
@spec scope_completed?(keyword()) :: {:ok, boolean()} | {:error, term()}
```

Whether the described stream scope is currently closed.

# `verify_content`

```elixir
@spec verify_content(
  non_neg_integer(),
  struct() | Chronicle.EventSequences.PreparedEvent.t(),
  keyword()
) :: {:ok, :equal | :different | :unavailable} | {:error, term()}
```

Verifies that `event` is what was stored at `sequence_number`, by comparing content. Accepts
either an event struct or a `Chronicle.EventSequences.PreparedEvent` from `EventLog.prepare/2`
(verifying against the content it already captured, without re-serializing).

Returns `{:ok, :equal | :different | :unavailable}`; `:unavailable` means the kernel could not
compare (for example the content was redacted). Returns `{:error, {:unknown_event_type, module}}`
when `event` does not `use Chronicle.Events.EventType`.

---

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