Skip to main content
Table of Contents

Interface IReadModelPreservation

Namespace
Stratara.Projections.Abstractions
Assembly
Stratara.Projections.dll

Keeps the read models a replay is about to empty, so a replay that fails — or whose host stops — leaves them as they were before it began instead of empty or half rebuilt.

public interface IReadModelPreservation
Extension Methods

Remarks

The replay worker uses an implementation when one is registered and replays exactly as without it otherwise. It preserves before it empties anything, restores after a failure that persisted through the batch retries, and discards after a replay that succeeded; a replay whose host stopped leaves the preserved state, and the next host that starts restores it through RestoreAbandonedAsync(CancellationToken).

What is preserved must be one consistent state: the read models together with what decides how they continue — the positions of projections that read the store and each projection's record of forgotten tenants — so the restored state is one that existed. AddReadModelRestore<TReadContext>() registers the PostgreSQL implementation.

A failure of the store itself — a connection that drops, a statement the database refuses — propagates as the store's own exception; the replay worker logs it, and a preserved state stays in place for the next attempt.

Methods

DiscardAsync(Guid, CancellationToken)

Drops the state preserved for replayId after the replay succeeded.

Task DiscardAsync(Guid replayId, CancellationToken cancellationToken = default)

Parameters

replayId Guid

The identity of the request the replay ran.

cancellationToken CancellationToken

Cancels the discard.

Returns

Task

A task that completes once the preserved state is dropped.

PreserveAsync(Guid, CancellationToken)

Preserves the read models for the replay replayId, before anything is emptied. Where a state preserved for a replay that did not finish is still kept, that state is kept and handed to this replay instead: it is the last complete one, and what is in place is partial.

Task PreserveAsync(Guid replayId, CancellationToken cancellationToken = default)

Parameters

replayId Guid

The identity of the request the replay runs.

cancellationToken CancellationToken

Cancels the preservation; nothing has been emptied when it is cancelled.

Returns

Task

A task that completes once the state is preserved.

Exceptions

InvalidOperationException

The read models cannot be preserved so that they could be restored — for example because a table outside them references one of them. Nothing has been emptied.

RestoreAbandonedAsync(CancellationToken)

Restores a preserved state that no running replay owns — left by a replay whose host stopped — and drops one whose replay succeeded but could not drop it. Hosts that start at once restore it once.

Task<AbandonedPreservation> RestoreAbandonedAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

Cancels the check.

Returns

Task<AbandonedPreservation>

What was found: nothing kept, a state restored, a state dropped, or a state a replay marked active still owns — which the caller checks again later, because a host that restarted within its replay's lease finds that replay still marked active.

RestoreAsync(Guid, CancellationToken)

Writes the state preserved for replayId back in place of what the replay rebuilt, as one step readers observe entirely or not at all, and drops it.

Task<bool> RestoreAsync(Guid replayId, CancellationToken cancellationToken = default)

Parameters

replayId Guid

The identity of the request the failed replay ran.

cancellationToken CancellationToken

Cancels the restoration, which then leaves the read models as they were.

Returns

Task<bool>

true when the state was restored; false when none is kept for the replay.

Exceptions

InvalidOperationException

The preserved state no longer fits the read models — a schema change ran in between. The preserved state is kept for the operator.