evoq_store_subscription (evoq v1.23.3)
View SourceBridge between event stores and evoq routing infrastructure.
Creates a single $all subscription to a reckon-db store, receiving ALL events in global store order. Events are filtered locally by checking against registered event types in the type registry.
This preserves causal ordering across event types within a store, which is critical when projections for related events must execute in the order they were appended (e.g., license_initiated before license_published).
How It Works
1. Replays all historical events from the store (catch-up phase) 2. Subscribes to the store's $all stream (by_stream, selector $all) 3. Receives ALL new events in store-global order 4. For each event, checks if any handler is registered for its type 5. Routes matching events to evoq_event_router and evoq_pm_router 6. Skips events with no registered handlers (zero cost)
Usage
Start one instance per event store:
%% In your application supervisor or startup:
evoq_store_subscription:start_link(plugins_store)
evoq_store_subscription:start_link(settings_store, #{})All modules implementing evoq behaviours that have registered with evoq_event_type_registry will automatically receive matching events.
Summary
Functions
Keep only the events matching EventType, in order. Exported for testing (pure, no store needed) -- backfill_loop/5 is the only real caller, and needs a live store to exercise past this point.
Start a store subscription with default options.
Start a store subscription with options.
Types
-type evoq_event() :: #evoq_event{event_id :: binary(), event_type :: binary() | undefined, stream_id :: binary(), version :: non_neg_integer(), data :: map() | binary(), metadata :: map(), tags :: [binary()] | undefined, timestamp :: integer(), epoch_us :: integer(), data_content_type :: binary(), metadata_content_type :: binary(), prev_event_hash :: binary() | undefined}.
Functions
-spec filter_by_type([evoq_event() | term()], binary()) -> [evoq_event() | term()].
Keep only the events matching EventType, in order. Exported for testing (pure, no store needed) -- backfill_loop/5 is the only real caller, and needs a live store to exercise past this point.
Start a store subscription with default options.
Start a store subscription with options.
No options are currently read from Opts -- catch-up always starts at 0 and the live $all subscription's own starting point is always whatever catch_up_historical/2 actually scanned up to (see handle_continue/2), not a caller-supplied position. Opts is still accepted and threaded through (subscribe_to_all/3 receives it) for a future option this shape doesn't need yet -- e.g. pool_size.