Marc/aa2 retry tran - #3139
Merged
Merged
Conversation
Introduces a retryable transaction, obtained via WithRetry(...).CreateTransaction(). Mechanism: RetryTransaction is an [AutoDatabase] recorder. The generator funnels each builder call into (state, projection) - the same captured unit RetryDatabase replays - which RetryTransaction records while handing the caller a durable, still-incomplete proxy task. ExecuteAsync runs the retry loop: each attempt spins up a fresh one-shot inner transaction against the underlying database (for multi-group this resolves the currently active member, so a retry after failover lands on the new member), replays the recorded ops and constraints onto it, and awaits it. On clean completion the per-attempt outcomes are forwarded onto the durable proxies; on a transient fault the attempt is discarded and replayed; on terminal failure the proxies are faulted. The transaction's effective retry category is the most side-effecting of its operations (WATCH constraints excluded); it is injected onto the EXEC flags so the resulting fault carries it and the shared RetryPolicy/FaultContext gating applies exactly as for a single command. Retry policy math is extracted into a shared RetryController used by both RetryDatabase and RetryTransaction. Surface (all [Experimental] SER007): - new ITransactionAsync (async-only transaction; sibling of ITransaction, no shipped-API change) - new IRetryDatabase with CreateTransaction; WithRetry now returns it - RedisTransaction/KeyPrefixedTransaction also implement ITransactionAsync Includes end-to-end tests: rides out a transient EXEC failure, respects the aggregate category gate, and does not double-apply a discarded attempt.
Reworks the retryable-transaction surface so WithRetry keeps returning IDatabaseAsync and RetryDatabase never has to implement IDatabase (which would drag in the sync surface). CreateTransaction now lives on IDatabaseAsync, returning the async-only ITransactionAsync; IDatabase.CreateTransaction refines the return type to ITransaction via "new", with ITransaction : IBatch, ITransactionAsync. To avoid any ambiguity, ITransaction re-declares AddCondition/ExecuteAsync(flags) with "new" rather than relying on inheritance, so its surface is self-contained and its shipped-API lines are unchanged. - IDatabaseAsync gains CreateTransaction(): ITransactionAsync ([Experimental] SER007) - IDatabase.CreateTransaction is now "new ITransaction ..." (signature unchanged) - ITransaction : IBatch, ITransactionAsync (re-declares its two async members) - the source generator skips CreateTransaction/CreateBatch (not replayable round-trips) - explicit IDatabaseAsync.CreateTransaction bridges on RedisDatabase, MultiGroupDatabase, KeyPrefixedDatabase; KeyPrefixed<TInner> base throws (reimplemented by the database); RetryTransaction throws (nested) - WithRetry returns IDatabaseAsync again; IRetryDatabase removed All retry/transaction/batch/keyprefix tests pass; full Release build across all TFMs.
ITransaction (stable) derives from ITransactionAsync, so the type must be stable too; the experimental gating stays on IDatabaseAsync.CreateTransaction (the new entry point). Also drops the now-redundant explicit ITransactionAsync from RedisTransaction and KeyPrefixedTransaction (implied by ITransaction : ITransactionAsync).
Now that CreateTransaction is on IDatabaseAsync, RetryTransaction only needs an IDatabaseAsync source: it creates each attempt's transaction via source.CreateTransaction() and uses only AddCondition/ExecuteAsync (both on ITransactionAsync). Removes the IDatabase cast and its NotSupportedException path, so WithRetry(...).CreateTransaction() works over any IDatabaseAsync.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implement transaction retries
Checklist