Skip to main content
Table of Contents

Class ProjectionTransactionExtensions

Namespace
Stratara.Projections
Assembly
Stratara.Projections.dll

Helpers for the write half of an idempotent projection.

public static class ProjectionTransactionExtensions
Inheritance
ProjectionTransactionExtensions
Inherited Members

Remarks

At-least-once delivery means a projection will see the same event twice, and cascading deletes mean a row can vanish between the read and the write. Neither is a fault. A second writer changing a row that still exists is, and it must keep stopping the bundle.

The other half of writing an idempotent projection needs no helper: load the row, and return when it is not there.

var tenant = await repository.GetAsync(@event.StreamId, cancellationToken);
if (tenant is null) { return; }

Methods

SaveChangesIdempotentAsync(ITransaction, Func<CancellationToken, Task<bool>>, CancellationToken)

Commits the transaction, treating a concurrency conflict as satisfied when the row the write targeted is gone — a concurrent bundle reached the same end state first.

public static Task<int> SaveChangesIdempotentAsync(this ITransaction transaction, Func<CancellationToken, Task<bool>> targetStillExists, CancellationToken cancellationToken = default)

Parameters

transaction ITransaction

The active read transaction.

targetStillExists Func<CancellationToken, Task<bool>>

Probes whether the write's target is still present. Evaluated only after a conflict. Return true if any targeted row still exists, which makes the conflict a real one.

cancellationToken CancellationToken

A token to cancel the operation.

Returns

Task<int>

The number of rows the commit affected, or 0 when the conflict was satisfied.

Exceptions

ConcurrencyConflictException

Rethrown when targetStillExists reports the row is still there. Suppressing it would turn "a failing projection stops the bundle" into a guarantee that holds only where nobody used this helper.