Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add configurable retry timing for RunTransactionAsync #11564

Merged
merged 1 commit into from
Jan 29, 2024

Conversation

jskeet
Copy link
Collaborator

@jskeet jskeet commented Jan 19, 2024

There are further changes to come in terms of transaction retry, but this is at least a start. Note that this changes the default backoff from "none at all" to "100ms initial, with a multiplier of 1.3". That's a more reasonable default, and it seems unlikely that customers would actually depend on there being no backoff.

Fixes #10513

@jskeet jskeet added the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Jan 19, 2024
@jskeet jskeet requested a review from a team as a code owner January 19, 2024 16:55
@jskeet
Copy link
Collaborator Author

jskeet commented Jan 19, 2024

Marked as "do not merge" as while this is the complete production code as far as I'm aware, there are no tests yet - I wanted to get feedback on the API and overall plan first.

@@ -410,8 +420,12 @@ public async Task<T> RunTransactionAsync<T>(Func<Transaction, Task<T>> callback,
}
catch (RpcException e) when (CheckRetry(e, ref rollback))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a bug here that was there before.

If commit fails with aborted and there are attempts left, we never rollback that failed transaction right? Or is it OK not to rollback it because it already failed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's okay, but we'll need to check. We definitely need to make changes here in general though - this PR is only attempting to affect the timing.

Comment on lines 426 to 428
// This is essentially the inner loop of RetryAttempt.CreateRetrySequence.
await scheduler.Delay(timing.BackoffJitter.GetDelay(backoff), cancellationToken).ConfigureAwait(false);
backoff = timing.NextBackoff(backoff);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is clearer inside the catch.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm generally nervous of doing stuff in catch blocks. There are some oddities about how code executes there - not that I can remember details. Let's chat next week.

@@ -24,27 +25,53 @@ public sealed class TransactionOptions
/// <summary>
/// The transaction options that are used if nothing is specified by the caller.
/// </summary>
public static TransactionOptions Default { get; } = new TransactionOptions(5);
public static TransactionOptions Default { get; } = new TransactionOptions(5, null);

/// <summary>
/// The number of times the transaction will be attempted before failing.
/// </summary>
public int MaxAttempts { get; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we deprecate this one instead of ignoring the one in RetrySettings?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels a bit like overkill if most people won't need to touch the timing - creating a retry setting is relatively complex. Happy to chat about it though.

@jskeet
Copy link
Collaborator Author

jskeet commented Jan 23, 2024

Revamped to just use an underlying RetrySettings - PTAL.

Copy link
Contributor

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

There are further changes to come in terms of transaction retry, but
this is at least a start. Note that this changes the default backoff
from "none at all" to "100ms initial, with a multiplier of 1.3".
That's a more reasonable default, and it seems unlikely that
customers would actually *depend* on there being no backoff.

Fixes googleapis#10513
@jskeet jskeet removed the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Jan 29, 2024
@jskeet
Copy link
Collaborator Author

jskeet commented Jan 29, 2024

I've added tests, and this is now ready to merge if you're happy with it. (Again, it's not the final word on transaction retries - but it's at least an improvement in terms of timing.)

@jskeet jskeet merged commit 4b1acf8 into googleapis:main Jan 29, 2024
9 checks passed
@jskeet jskeet deleted the issue-10513 branch January 29, 2024 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Google.Cloud.Firestore: Backoff on FirestoreDb.RunTransactionAsync retry
2 participants