Idiomatic Elixir interface for ad-hoc projection querying and waiting for a registered projection to catch up.
query/2 sends a Projection Declaration Language (PDL) string straight to the kernel and
returns the projected entries, without registering a permanent projection or defining a read
model module. preview/2 does the same for an already-registered projection's own
declaration. Mirrors the C# client's IProjections.Query().
:::caution Every call replays events from the beginning of the event sequence, up to an internal kernel limit. Use this for tooling, diagnostics and tests over small, bounded event volumes - not in a high-throughput code path. :::
Ad-hoc querying
{:ok, result} =
Chronicle.Projections.query("""
projection OrderSummary
from OrderPlaced
""")
result.instances # decoded as plain maps unless `:read_model` is given
result.total_countPass :read_model to decode the entries as a struct instead of plain maps:
{:ok, result} = Chronicle.Projections.query(declaration, read_model: MyApp.ReadModels.Order)A declaration with syntax or type errors returns
{:error, {:invalid_declaration, [%{message: ..., line: ..., column: ...}]}}.
Previewing a registered projection
{:ok, result} = Chronicle.Projections.preview(MyApp.ReadModels.Order)Looks up the declaration already registered for the read model (or projection identifier) and
runs it the same way query/2 does. Returns {:error, {:unknown_projection, id}} when no
declaration is registered under that identifier.
Waiting for a projection
:ok = Chronicle.Projections.wait_for(MyApp.ReadModels.Order, sequence_number)Polls the projection's observer state until it has handled at least sequence_number, or
returns {:error, :timeout}.
Common options
:client— the client name (default:Chronicle.Client):namespace— overrides the client's configured namespace:event_sequence_id— event sequence identifier (default:"event-log")
Summary
Functions
Looks up the declaration already registered for a read model or projection identifier, and
runs it through query/2.
Queries a PDL declaration against the event log without registering it.
Waits until the projection that maintains module_or_id has handled at least
sequence_number, polling Chronicle.Observers.get_all/1.
Functions
@spec preview(module() | String.t(), keyword()) :: {:ok, Chronicle.ReadModels.QueryResult.t()} | {:error, {:invalid_declaration, [map()]}} | {:error, {:unknown_projection, module() | String.t()}} | {:error, term()}
Looks up the declaration already registered for a read model or projection identifier, and
runs it through query/2.
Returns {:error, {:unknown_projection, module_or_id}} when no declaration is registered under
that identifier.
Options
Accepts :read_model like query/2 (defaults to module_or_id when it is a module), plus the
common options.
@spec query(String.t(), keyword()) :: {:ok, Chronicle.ReadModels.QueryResult.t()} | {:error, {:invalid_declaration, [map()]}} | {:error, term()}
Queries a PDL declaration against the event log without registering it.
The declaration may omit => ReadModelType, in which case the read model schema is inferred
from the events it uses; an inferred declaration can never be saved as a permanent projection.
Returns {:ok, %Chronicle.ReadModels.QueryResult{}}, or
{:error, {:invalid_declaration, [%{message: String.t(), line: integer(), column: integer()}]}}
when the declaration has syntax or type errors.
Options
:read_model— decode each entry as this struct instead of a plain map- (see module documentation for the common options)
@spec wait_for(module() | String.t(), non_neg_integer(), keyword()) :: :ok | {:error, :timeout}
Waits until the projection that maintains module_or_id has handled at least
sequence_number, polling Chronicle.Observers.get_all/1.
Returns :ok, or {:error, :timeout} once :timeout (default 5000 ms)
elapses.
Options
:timeout— maximum time to wait in milliseconds (default5000):interval— delay between polls in milliseconds (default50)- (see module documentation for the common options)