Class UnitOfWork

Namespace
Cratis.Chronicle.Transactions
Assembly
Cratis.Chronicle.dll

Represents an implementation of IUnitOfWork.

public class UnitOfWork : IUnitOfWork, IDisposable
Inheritance
UnitOfWork
Implements
Inherited Members
Extension Methods

Constructors

UnitOfWork(CorrelationId, Action<IUnitOfWork>, IEventStore, UnitOfWorkLifecyclePolicy, ILogger<UnitOfWork>?)

Initializes a unit of work with the given lifecycle policy.

public UnitOfWork(CorrelationId correlationId, Action<IUnitOfWork> onCompleted, IEventStore eventStore, UnitOfWorkLifecyclePolicy lifecyclePolicy, ILogger<UnitOfWork>? logger = null)

Parameters

correlationId CorrelationId

The correlation identifier.

onCompleted Action<IUnitOfWork>

Called on completion.

eventStore IEventStore

The event store.

lifecyclePolicy UnitOfWorkLifecyclePolicy

The lifecycle policy.

logger ILogger<UnitOfWork>

Optional logger for late staging diagnostics.

UnitOfWork(CorrelationId, Action<IUnitOfWork>, IEventStore, IActivitySource<UnitOfWork>?)

Initializes a unit of work with compatibility staging behavior.

public UnitOfWork(CorrelationId correlationId, Action<IUnitOfWork> onCompleted, IEventStore eventStore, IActivitySource<UnitOfWork>? activitySource = null)

Parameters

correlationId CorrelationId

The correlation identifier.

onCompleted Action<IUnitOfWork>

Called on completion.

eventStore IEventStore

The event store.

activitySource IActivitySource<UnitOfWork>

Optional activity source for tracing.

UnitOfWork(CorrelationId, Action<IUnitOfWork>, IEventStore, IActivitySource<UnitOfWork>?, UnitOfWorkLifecyclePolicy, ILogger<UnitOfWork>?)

Initializes a new instance of the UnitOfWork class.

public UnitOfWork(CorrelationId correlationId, Action<IUnitOfWork> onCompleted, IEventStore eventStore, IActivitySource<UnitOfWork>? activitySource, UnitOfWorkLifecyclePolicy lifecyclePolicy, ILogger<UnitOfWork>? logger = null)

Parameters

correlationId CorrelationId

The correlation identifier.

onCompleted Action<IUnitOfWork>

Called on completion.

eventStore IEventStore

The event store.

activitySource IActivitySource<UnitOfWork>

Optional activity source for tracing.

lifecyclePolicy UnitOfWorkLifecyclePolicy

The policy for staging after completion begins.

logger ILogger<UnitOfWork>

Optional logger for late staging diagnostics.

Properties

CorrelationId

Gets the CorrelationId for the IUnitOfWork.

public CorrelationId CorrelationId { get; }

Property Value

CorrelationId

EffectReceipt

Gets the winning receipt after a successful receipted commit.

public EffectReceiptResult? EffectReceipt { get; }

Property Value

EffectReceiptResult

HasEnrolledDecisionReads

Gets a value indicating whether a decision read has ever been successfully enrolled in this unit of work.

public bool HasEnrolledDecisionReads { get; }

Property Value

bool

Remarks

Once true, the value remains true after commit, rollback, or disposal. Custom implementations that do not override this property report false by default.

IsCompleted

Gets the value indicating whether the unit of work is completed.

public bool IsCompleted { get; }

Property Value

bool

Remarks

Unit of work being completed is semantically equal to it being disposed.

IsEnforcingReadProtection

Gets whether this unit permanently uses enforced read protection and a strict lifecycle.

public bool IsEnforcingReadProtection { get; }

Property Value

bool

IsSuccess

Gets a value indicating whether the IUnitOfWork was successful.

public bool IsSuccess { get; }

Property Value

bool

Methods

AddDecisionRead(IDecisionRead)

Enroll a protected read as a commit dependency.

public void AddDecisionRead(IDecisionRead read)

Parameters

read IDecisionRead

The protected read.

Exceptions

UnitOfWorkDecisionReadsNotSupported

This implementation does not support decision reads.

AddEnrollmentContributor(IUnitOfWorkEnrollmentContributor)

Attaches a contributor for the lifetime of an enrollment scope, such as one command invocation.

public IDisposable AddEnrollmentContributor(IUnitOfWorkEnrollmentContributor contributor)

Parameters

contributor IUnitOfWorkEnrollmentContributor

The contributor to consult before enrollment.

Returns

IDisposable

A handle that removes only this registration on disposal.

Exceptions

UnitOfWorkEnrollmentContributorsNotSupported

The implementation does not support contributors.

UnitOfWorkMutatedDuringEnrollment

A contributor attempted to change registrations.

AddEvent(EventSequenceId, EventSourceId, object, Causation, EventStreamType?, EventStreamId?, EventSourceType?, ConcurrencyScope?, IEnumerable<string>?, DateTimeOffset?, Subject?)

Add an event that has occurred to the IUnitOfWork.

public void AddEvent(EventSequenceId eventSequenceId, EventSourceId eventSourceId, object @event, Causation causation, EventStreamType? eventStreamType = null, EventStreamId? eventStreamId = null, EventSourceType? eventSourceType = null, ConcurrencyScope? concurrencyScope = null, IEnumerable<string>? tags = null, DateTimeOffset? occurred = null, Subject? subject = null)

Parameters

eventSequenceId EventSequenceId

The EventSequenceId for the event.

eventSourceId EventSourceId

The EventSourceId for the event.

event object

The event that has occurred.

causation Causation

The Causation for the event.

eventStreamType EventStreamType

Optional EventStreamType for the event, will default to the All stream if not set.

eventStreamId EventStreamId

Optional EventStreamId for the event, will default to Default is not set.

eventSourceType EventSourceType

Optional EventSourceType for the event, will default to Default is not set.

concurrencyScope ConcurrencyScope

Optional ConcurrencyScope for the event, will default to NotSet if not set.

tags IEnumerable<string>

Optional dynamic tags to associate with the event.

occurred DateTimeOffset?

Optional timestamp for when the event occurred.

subject Subject

Optional subject identifying what the event is about.

AddEventWithNamedTags(EventSequenceId, EventSourceId, object, IEnumerable<NamedTag>, Causation, EventStreamType?, EventStreamId?, EventSourceType?, ConcurrencyScope?, IEnumerable<string>?, DateTimeOffset?, Subject?)

Add an event with structured named tags.

public void AddEventWithNamedTags(EventSequenceId eventSequenceId, EventSourceId eventSourceId, object @event, IEnumerable<NamedTag> namedTags, Causation causation, EventStreamType? eventStreamType = null, EventStreamId? eventStreamId = null, EventSourceType? eventSourceType = null, ConcurrencyScope? concurrencyScope = null, IEnumerable<string>? tags = null, DateTimeOffset? occurred = null, Subject? subject = null)

Parameters

eventSequenceId EventSequenceId

The event sequence.

eventSourceId EventSourceId

The event source.

event object

The event.

namedTags IEnumerable<NamedTag>

Structured named tags.

causation Causation

The causation.

eventStreamType EventStreamType

Optional stream type.

eventStreamId EventStreamId

Optional stream id.

eventSourceType EventSourceType

Optional source type.

concurrencyScope ConcurrencyScope

Optional concurrency scope.

tags IEnumerable<string>

Optional plain tags.

occurred DateTimeOffset?

Optional occurred time.

subject Subject

Optional subject.

Exceptions

UnitOfWorkNamedTagsNotSupported

The implementation cannot carry nonempty named tags.

AddEventWithOptions(EventSequenceId, EventSourceId, object, Causation, EventEnrollmentOptions)

Enrolls an event with its scope origin. Alternate implementations retain their existing enrollment behavior.

public void AddEventWithOptions(EventSequenceId eventSequenceId, EventSourceId eventSourceId, object @event, Causation causation, EventEnrollmentOptions options)

Parameters

eventSequenceId EventSequenceId

The event sequence.

eventSourceId EventSourceId

The event source.

event object

The event.

causation Causation

The causation.

options EventEnrollmentOptions

The enrollment options.

Exceptions

ConcurrencyScopeOriginNotValidForEvents

The origin is reserved for reads.

AddEvents(EventSequenceId, IEnumerable<EventForEventSourceId>, IEnumerable<KeyValuePair<EventSourceId, ConcurrencyScope>>)

Adds an ordered batch of events and independently labeled concurrency scopes to the IUnitOfWork.

public void AddEvents(EventSequenceId eventSequenceId, IEnumerable<EventForEventSourceId> events, IEnumerable<KeyValuePair<EventSourceId, ConcurrencyScope>> concurrencyScopes)

Parameters

eventSequenceId EventSequenceId

The EventSequenceId for the events.

events IEnumerable<EventForEventSourceId>

The events to add, in commit order.

concurrencyScopes IEnumerable<KeyValuePair<EventSourceId, ConcurrencyScope>>

The concurrency scopes to validate with the batch.

Remarks

Both inputs are materialized before this method returns. Consecutive single-event enrollments retain their legacy source-grouped order. Each call to this method forms a globally ordered segment between those legacy segments, and commit flattens every segment into one append operation. A concurrency-scope key can be an independent label when its scope does not narrow by event-source ID. For event-target labels, a missing or NotSet scope retains the configured strategy. An independent non-target label must use a concrete exact scope or None.

Exceptions

ConcurrencyScopeLabelMustBeSpecified

Thrown when an event target or scope label is unspecified, blank, or whitespace.

ConcurrencyScopeEventSourceIdDoesNotMatchLabel

Thrown when a scope narrows by an event source different from its label.

DuplicateConcurrencyScopeForEventSourceId

Thrown when more than one scope has the same label in one enrollment.

ConflictingConcurrencyScopesForLabel

Thrown when a label already has a different explicit scope in this unit of work.

IndependentConcurrencyScopeMustBeExplicit

Thrown when an independent non-target label does not have a concrete exact scope or None.

UnitOfWorkCannotSpanEventSequences

Thrown when this unit of work is already bound to another event sequence.

UnitOfWorkBatchEnrollmentNotSupported

Thrown when an alternate unit-of-work implementation does not support ordered batch enrollment.

AddEvents(EventSequenceId, IEnumerable<EventForEventSourceId>, IEnumerable<KeyValuePair<EventSourceId, ConcurrencyScope>>, ConcurrencyScopeOrigin)

Enrolls an ordered batch with the origin of its supplied scopes.

public void AddEvents(EventSequenceId eventSequenceId, IEnumerable<EventForEventSourceId> events, IEnumerable<KeyValuePair<EventSourceId, ConcurrencyScope>> concurrencyScopes, ConcurrencyScopeOrigin origin)

Parameters

eventSequenceId EventSequenceId

The event sequence.

events IEnumerable<EventForEventSourceId>

The ordered events.

concurrencyScopes IEnumerable<KeyValuePair<EventSourceId, ConcurrencyScope>>

The supplied scopes.

origin ConcurrencyScopeOrigin

The scope contribution.

Exceptions

ConcurrencyScopeOriginNotValidForEvents

The origin is reserved for reads.

AllowReads(ReadAllowance, string)

Allows explicit reads without permitting immediate appends or removing existing dependencies.

public IDisposable AllowReads(ReadAllowance allowance, string reason)

Parameters

allowance ReadAllowance

Advisory reads or reads contributed before exposure.

reason string

The explicit reason for the region.

Returns

IDisposable

The flow-local read region.

Exceptions

UnitOfWorkReadProtectionNotSupported

The implementation cannot support allowances.

ReadProtectionAllowanceNotValid

The allowance or reason is invalid.

ClaimDecisionReadCommitOwnership()

Claims exclusive completion ownership for protected units of work.

public DecisionReadCommitOwner ClaimDecisionReadCommitOwnership()

Returns

DecisionReadCommitOwner

The opaque owner capability.

Exceptions

ProtectedUnitOfWorkRequiresOwner

An owner has already claimed this unit.

Commit()

Commit the IUnitOfWork.

public Task Commit()

Returns

Task

Awaitable task.

CommitAsOwner(DecisionReadCommitOwner)

Commits using the capability obtained by the transaction owner.

public Task CommitAsOwner(DecisionReadCommitOwner owner)

Parameters

owner DecisionReadCommitOwner

The claimed owner capability.

Returns

Task

The commit task.

Exceptions

ProtectedUnitOfWorkRequiresOwner

A different owner attempted to complete the unit.

Dispose()

public void Dispose()

Remarks

Disposal during an in-flight commit is a no-op; the commit completes the unit.

Exceptions

ProtectedUnitOfWorkRequiresOwner

A claimed, open unit with enrolled decision reads must be completed by its owner.

EnforceReadProtection()

Begins invocation read protection before any event or read dependency is enrolled. Only the first caller receives the owning lifetime; subsequent leases cannot end enforcement.

public ReadProtectionFrame EnforceReadProtection()

Returns

ReadProtectionFrame

The invocation frame, disposed by the owning command pipeline in a finally block.

Exceptions

UnitOfWorkReadProtectionNotSupported

The implementation cannot enforce read protection.

ReadProtectionMustBeginBeforeEnrollment

Events or dependencies have already been enrolled.

EnrolContributedRead(ContributedRead)

Atomically validates target, staged overlap and distinct contributions before enrolling a read.

public void EnrolContributedRead(ContributedRead contribution)

Parameters

contribution ContributedRead

The stream or aggregate dependency.

Exceptions

UnitOfWorkReadProtectionNotSupported

The implementation cannot enroll contributions.

ContributedReadOriginNotValid

The contribution is not explicit or aggregate.

GetAppendConditions()

Gets the append conditions captured by the trusted commit.

public IReadOnlyList<AppendCondition> GetAppendConditions()

Returns

IReadOnlyList<AppendCondition>

The immutable append-condition descriptions.

GetAppendErrors()

Get any errors that have occurred while attempting to commit in the IUnitOfWork.

public IEnumerable<AppendError> GetAppendErrors()

Returns

IEnumerable<AppendError>

A collection of AppendError.

GetConcurrencyViolations()

Gets any concurrency violations thar occurred in the IUnitOfWork.

public IEnumerable<ConcurrencyViolation> GetConcurrencyViolations()

Returns

IEnumerable<ConcurrencyViolation>

A collection of ConcurrencyViolation.

GetConstraintViolations()

Gets any constraint violations that occurred in the IUnitOfWork.

public IEnumerable<ConstraintViolation> GetConstraintViolations()

Returns

IEnumerable<ConstraintViolation>

A collection of ConstraintViolation.

GetDecisionConflicts()

Gets the decision conflicts that refused the commit.

public IEnumerable<DecisionConflict> GetDecisionConflicts()

Returns

IEnumerable<DecisionConflict>

Decision conflicts, if any, with the first conflicting event when the kernel reported it.

GetEvents()

Get the events that have occurred in the IUnitOfWork.

public IEnumerable<object> GetEvents()

Returns

IEnumerable<object>

A collection of events.

OnCompleted(Action<IUnitOfWork>)

Set callback to be called when completed.

public void OnCompleted(Action<IUnitOfWork> callback)

Parameters

callback Action<IUnitOfWork>

The callback to call.

RefuseImmediateAppends()

Refuses immediate appends in this asynchronous flow without changing read admission. The first caller owns completion only if no completion owner or enforced read protection already exists. Otherwise the frame is refusal-only and completion stays with the existing owner. Later acquisitions cannot complete the unit or end refusal.

public ImmediateAppendRefusal RefuseImmediateAppends()

Returns

ImmediateAppendRefusal

The refusal lifetime, or a borrowed frame for a nested acquisition. Commit through the existing owner when present.

Exceptions

UnitOfWorkImmediateAppendRefusalNotSupported

The implementation cannot enforce append admission.

ImmediateAppendRefusalRequiresOwner

Another unit owns the active refusal.

Rollback()

Rollback the IUnitOfWork.

public Task Rollback()

Returns

Task

Awaitable task.

Exceptions

ProtectedUnitOfWorkRequiresOwner

A claimed unit with enrolled decision reads must be rolled back by its owner.

UnitOfWorkIsCompleting

A commit is in progress under the strict policy, or a claimed unit with enrolled decision reads is committing under the compatibility policy.

UnitOfWorkIsAlreadyCommitted

The unit has already been committed.

UnitOfWorkIsAlreadyRolledBack

The unit has already been rolled back.

RollbackAsOwner(DecisionReadCommitOwner)

Rolls back using the capability obtained by the transaction owner.

public Task RollbackAsOwner(DecisionReadCommitOwner owner)

Parameters

owner DecisionReadCommitOwner

The claimed owner capability.

Returns

Task

The rollback task.

Exceptions

ProtectedUnitOfWorkRequiresOwner

The capability does not match the claimed owner, or no owner has been claimed.

UnitOfWorkIsCompleting

A commit is in progress, regardless of lifecycle policy.

UnitOfWorkIsAlreadyCommitted

The unit has already been committed.

UnitOfWorkIsAlreadyRolledBack

The unit has already been rolled back.

SuspendReadRegions()

Suspends the read regions this asynchronous flow inherited, without ending read protection.

public IDisposable SuspendReadRegions()

Returns

IDisposable

The suspension, disposed by the host when the nested invocation ends.

Remarks

A read region flows with the asynchronous context, so a region opened by an outer invocation also covers a nested invocation it runs. A host that runs nested invocations under the same read protection suspends the inherited regions at the start of the nested one: reads are then refused as if no region were open, while regions opened inside the suspension apply as usual. Disposing the returned scope restores the inherited regions. Suspensions nest.

Exceptions

UnitOfWorkReadProtectionNotSupported

The implementation cannot support read regions.

ReadProtectionUnitMismatch

The unit does not own the active invocation.

TryGetLastCommittedEventSequenceNumber(out EventSequenceNumber?)

Try to get the EventSequenceNumber of the last committed event.

public bool TryGetLastCommittedEventSequenceNumber(out EventSequenceNumber? eventSequenceNumber)

Parameters

eventSequenceNumber EventSequenceNumber

The outputted EventSequenceNumber of the last committed event.

Returns

bool

True if events were committed, false if not.

UseEffectReceipt(EffectKey, JsonNode?)

Enrolls one effect key in this unit's atomic commit. Re-enrolling the same key replaces its response until completion begins.

public void UseEffectReceipt(EffectKey key, JsonNode? response = null)

Parameters

key EffectKey

The occurrence effect key.

response JsonNode

Optional plaintext JSON response without personal data.

Exceptions

EffectReceiptsNotSupported

Atomic receipt support is absent or unknown.

EffectReceiptResponseTooLarge

The response exceeds 64 KiB of UTF-8 JSON.

UnitOfWorkEffectReceiptAlreadySet

Another key is already enrolled.