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
replayIdGuidThe identity of the request the replay ran.
cancellationTokenCancellationTokenCancels 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
replayIdGuidThe identity of the request the replay runs.
cancellationTokenCancellationTokenCancels 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
cancellationTokenCancellationTokenCancels 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
replayIdGuidThe identity of the request the failed replay ran.
cancellationTokenCancellationTokenCancels the restoration, which then leaves the read models as they were.
Returns
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.