Interface IEventStore
- Namespace
- Opossum
- Assembly
- Opossum.dll
public interface IEventStore
- Extension Methods
Methods
AppendAsync(NewEvent[], AppendCondition?, CancellationToken)
Atomically appends one or more events to the event store, optionally enforcing a concurrency guard.
Task AppendAsync(NewEvent[] events, AppendCondition? condition, CancellationToken cancellationToken = default)
Parameters
eventsNewEvent[]One or more events to append. The array must not be empty and every Event must have a non-empty EventType.
conditionAppendConditionOptional AppendCondition that guards the append against concurrent writes. Pass null for an unconditional append.
cancellationTokenCancellationTokenToken to cancel the operation. When cancelled, the semaphore wait is aborted and no events are written.
Returns
Exceptions
- AppendConditionFailedException
Thrown when
conditionis set and a conflicting event was appended between the caller's read and this append. Catch this exception and retry the full read → decide → append cycle.- ArgumentNullException
When
eventsis null.- ArgumentException
When
eventsis empty or contains an event with a null/empty EventType.- TimeoutException
Thrown when the cross-process append lock cannot be acquired within CrossProcessLockTimeout. This can occur when multiple application instances share the same store directory and one instance holds the lock for an unusually long time. Increase CrossProcessLockTimeout if this occurs regularly, or investigate the process that is holding the lock.
ReadAsync(Query, ReadOption[]?, long?, int?)
Reads events matching query from the event store.
Task<SequencedEvent[]> ReadAsync(Query query, ReadOption[]? readOptions, long? fromPosition = null, int? maxCount = null)
Parameters
queryQueryFilter — use All() to read every event.
readOptionsReadOption[]Optional read options (e.g. Descending).
fromPositionlong?When provided, only events with
Position > fromPositionare returned. Pass the highest position already processed to resume reading from a known checkpoint. When null (the default) all matching events are returned.maxCountint?When provided, at most this many events are returned. Combine with
fromPositionto page through large result sets without loading all events into memory at once. When null (the default) all matching events are returned.
Returns
ReadLastAsync(Query, CancellationToken)
Returns the event with the highest sequence position that matches query,
or null when the store contains no matching events.
Task<SequencedEvent?> ReadLastAsync(Query query, CancellationToken cancellationToken = default)
Parameters
queryQueryFilter — use All() to find the globally last event.
cancellationTokenCancellationTokenToken to cancel the operation.
Returns
- Task<SequencedEvent>
The matching event with the highest sequence position, or null when no events in the store match
query.
Remarks
This is the efficient read step for DCB patterns that require knowledge of only the most
recent event of a given type — for example, reading the last InvoiceCreatedEvent
to determine the next invoice number in an unbroken monotonic sequence.
Typical DCB pattern for consecutive sequences:
// Step 1 — Read: find the last invoice event
var query = Query.FromEventTypes(nameof(InvoiceCreatedEvent));
var last = await eventStore.ReadLastAsync(query);
// Step 2 — Decide: derive the next number
var nextNumber = last is null ? 1 : ((InvoiceCreatedEvent)last.Event.Event).InvoiceNumber + 1;
// Step 3 — Append with a guard that fails if any new invoice appeared in the meantime
var condition = new AppendCondition
{
FailIfEventsMatch = query,
AfterSequencePosition = last?.Position // null → reject if ANY invoice already exists
};
await eventStore.AppendAsync([new NewEvent { Event = new InvoiceCreatedEvent(nextNumber) }], condition);
// Throws AppendConditionFailedException on conflict — retry the full cycle.
Only one event file is read from storage regardless of how many total events match
the query, making this significantly more efficient than
ReadAsync(..., [ReadOption.Descending])[0] for large event streams.
Exceptions
- ArgumentNullException
When
queryis null.