Represents a concurrency scope for Chronicle append operations.
Concurrency scopes let you assert the expected tail sequence number before appending one or more events. You can optionally narrow the check to the current event source, stream, source type, and event types.
alias Chronicle.Events.ConcurrencyScope
scope =
ConcurrencyScope.for_event_source(3,
event_types: [MyApp.Events.FundsDeposited, MyApp.Events.FundsWithdrawn]
)
:ok = Chronicle.append_many("account-42", [...], concurrency_scope: scope)The event_source_id option is a boolean because the actual event source id
comes from the Chronicle.append/3 or Chronicle.append_many/3 call.
Summary
Functions
Reads the current tail sequence number for event_source_id - narrowed the same way the
returned scope narrows, via :event_stream_type, :event_stream_id, :event_source_type
and :event_types - and returns a scope expecting that tail. A live-read shortcut for
for_event_source(tail, opts), mirroring .NET's ConcurrencyScopeBuilder combined with a
tail read (the pattern the optimistic strategy itself follows).
Creates a scope asserting that no event matches the scope's dimensions yet - the guard for creation-only operations ("this event source must not have been registered already").
Creates a concurrency scope that includes the current append event source id.
Creates a new concurrency scope.
Returns the sentinel scope representing no explicit concurrency constraint.
Includes the current append's event source id in the scope. Mirrors .NET's
ConcurrencyScopeBuilder.WithEventSourceId().
Narrows the scope to a specific event source type. Mirrors .NET's
ConcurrencyScopeBuilder.WithEventSourceType().
Narrows the scope to a specific event stream id. Mirrors .NET's
ConcurrencyScopeBuilder.WithEventStreamId().
Narrows the scope to a specific event stream type. Mirrors .NET's
ConcurrencyScopeBuilder.WithEventStreamType().
Adds a single event type to the scope's narrowing. Mirrors .NET's
ConcurrencyScopeBuilder.WithEventType().
Adds a list of event types to the scope's narrowing. Mirrors .NET's repeated
ConcurrencyScopeBuilder.WithEventType() calls.
Sets the expected sequence number on a scope. Pipe-able continuation of new/2,
for_event_source/2, or any other scope - mirrors .NET's
ConcurrencyScopeBuilder.WithSequenceNumber().
Types
@type event_type_module() :: module()
@type t() :: %Chronicle.Events.ConcurrencyScope{ event_source_id: boolean(), event_source_type: String.t(), event_stream_id: String.t(), event_stream_type: String.t(), event_types: [event_type_module()], expects_no_matching_event: boolean(), sequence_number: non_neg_integer() }
Functions
Reads the current tail sequence number for event_source_id - narrowed the same way the
returned scope narrows, via :event_stream_type, :event_stream_id, :event_source_type
and :event_types - and returns a scope expecting that tail. A live-read shortcut for
for_event_source(tail, opts), mirroring .NET's ConcurrencyScopeBuilder combined with a
tail read (the pattern the optimistic strategy itself follows).
{:ok, scope} = ConcurrencyScope.at_tail("account-1", event_stream_type: "Transactions")
Chronicle.append("account-1", %FundsDeposited{amount: 10}, concurrency_scope: scope)Accepts :client, :namespace and :event_sequence_id in addition to the narrowing
options above. Returns {:error, reason} when the tail read itself fails.
Creates a scope asserting that no event matches the scope's dimensions yet - the guard for creation-only operations ("this event source must not have been registered already").
Mirrors .NET's ConcurrencyScopeBuilder.ExpectingNoMatchingEvent(). It sends the kernel's explicit
no-matching-event condition; leaving the sequence number unset is not a substitute, because
that disables the check instead of asserting anything. The narrowing options are those of
new/2 - typically the event source and the event types that would make the append invalid:
scope =
ConcurrencyScope.expecting_no_matching_event(
event_source_id: true,
event_types: [MyApp.Events.UserRegistered]
)
Chronicle.append("user-1", %UserRegistered{}, concurrency_scope: scope)
@spec for_event_source(non_neg_integer(), [option()]) :: t()
Creates a concurrency scope that includes the current append event source id.
@spec new(non_neg_integer(), [option()]) :: t()
Creates a new concurrency scope.
@spec none() :: t()
Returns the sentinel scope representing no explicit concurrency constraint.
Includes the current append's event source id in the scope. Mirrors .NET's
ConcurrencyScopeBuilder.WithEventSourceId().
Narrows the scope to a specific event source type. Mirrors .NET's
ConcurrencyScopeBuilder.WithEventSourceType().
Narrows the scope to a specific event stream id. Mirrors .NET's
ConcurrencyScopeBuilder.WithEventStreamId().
Narrows the scope to a specific event stream type. Mirrors .NET's
ConcurrencyScopeBuilder.WithEventStreamType().
@spec with_event_type(t(), event_type_module()) :: t()
Adds a single event type to the scope's narrowing. Mirrors .NET's
ConcurrencyScopeBuilder.WithEventType().
@spec with_event_types(t(), [event_type_module()]) :: t()
Adds a list of event types to the scope's narrowing. Mirrors .NET's repeated
ConcurrencyScopeBuilder.WithEventType() calls.
@spec with_sequence_number(t(), non_neg_integer()) :: t()
Sets the expected sequence number on a scope. Pipe-able continuation of new/2,
for_event_source/2, or any other scope - mirrors .NET's
ConcurrencyScopeBuilder.WithSequenceNumber().