Skip to content

Don't delay retryable operations #3270

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

Merged
merged 2 commits into from
Jun 24, 2020
Merged

Conversation

schmidt-sebastian
Copy link
Contributor

@schmidt-sebastian schmidt-sebastian commented Jun 24, 2020

One of the behavior changes of enqueueRetryable (#2879) was that it only scheduled the next operation when the first operation succeeds. This means that any operation that was scheduled after the second retryable operation will run before this run:

enqueue(console.log(1))
enqueueRetryable(console.log(2))
enqueueRetryable(console.log(3))
enqueue(console.log(4))

-> prints 1,2,4,3 since 3 is only enqueued once 2 finishes

While theoretically okay, this still seems to cause some issues with the user change. This PR changes the retry behavior so that operations run in the original order if no failure occurred.

Addresses #3218

@google-oss-bot
Copy link
Contributor

google-oss-bot commented Jun 24, 2020

Binary Size Report

Affected SDKs

  • @firebase/firestore

    Type Base (c436bcc) Head (aec0915) Diff
    browser 248 kB 248 kB +79 B (+0.0%)
    esm2017 194 kB 194 kB -16 B (-0.0%)
    main 493 kB 493 kB +37 B (+0.0%)
    module 246 kB 246 kB +79 B (+0.0%)
  • @firebase/firestore/lite

    Type Base (c436bcc) Head (aec0915) Diff
    main 140 kB 140 kB -53 B (-0.0%)
  • @firebase/firestore/memory

    Type Base (c436bcc) Head (aec0915) Diff
    browser 186 kB 186 kB +79 B (+0.0%)
    esm2017 145 kB 145 kB -16 B (-0.0%)
    main 363 kB 363 kB +37 B (+0.0%)
    module 184 kB 184 kB +79 B (+0.0%)
  • firebase

    Type Base (c436bcc) Head (aec0915) Diff
    firebase-firestore.js 287 kB 287 kB +78 B (+0.0%)
    firebase-firestore.memory.js 226 kB 226 kB +78 B (+0.0%)
    firebase.js 820 kB 820 kB +78 B (+0.0%)

Test Logs

Copy link
Contributor

@var-const var-const left a comment

Choose a reason for hiding this comment

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

A couple of comments on the PR's description:

One of the behavior changes of enqueueRetryable was...
Can you add a link to the PR with the change?

This means that any operation that was scheduled after the second retryable operation will run before this run.

Can you rephrase and/or expand this sentence? I don't fully understand how this follows from the behavior change mentioned in the previous sentence.

@@ -313,6 +312,65 @@ describe('AsyncQueue', () => {
expect(completedSteps).to.deep.equal([1, 1, 2]);
});

it('Doesn not delay retryable operations that succeed', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: s/Doesn/Does/.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops. Fixed.

private async retryNextOp(): Promise<void> {
const op = this.retryableOps.shift();

if (op) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you use an early return instead to reduce nestedness?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated. I also ended up rewriting this a little bit to make flow easier to follow.

});
}

this.backoff.backoffAndRun(() => this.retryNextOp());
Copy link
Contributor

Choose a reason for hiding this comment

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

Question: why is backoff invoked in the successful case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a comment.

@@ -207,9 +207,9 @@ export class AsyncQueue {
// The last promise in the queue.
private tail: Promise<unknown> = Promise.resolve();

// The last retryable operation. Retryable operation are run in order and
// A list of retryable operations Retryable operation are run in order and
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: missing full stop.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

@@ -207,9 +207,9 @@ export class AsyncQueue {
// The last promise in the queue.
private tail: Promise<unknown> = Promise.resolve();

// The last retryable operation. Retryable operation are run in order and
// A list of retryable operations Retryable operation are run in order and
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: should be Retryable operations are run in order... (i.e. plural).

@@ -787,6 +787,7 @@ describeSpec('Persistence Recovery', ['no-ios', 'no-android'], () => {
.expectActiveTargets({ query })
// We are now user 2
.expectEvents(query, { removed: [doc1], fromCache: true })
.runTimer(TimerId.AsyncQueueRetry)
Copy link
Contributor

Choose a reason for hiding this comment

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

Question: why is this change necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The previous implementation used "enqueue" to run the next delayed operation, this implementation uses "enqueueWithBackoff". I verified that the backoff is 0 at this step, but even operations with zero backoff aren't automatically drained in the SpecTestRunner.

Copy link
Contributor

@var-const var-const left a comment

Choose a reason for hiding this comment

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

Can you please take a look at the comments regarding the PR's description? Thanks!

Copy link
Contributor Author

@schmidt-sebastian schmidt-sebastian left a comment

Choose a reason for hiding this comment

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

PR comment updated.

@schmidt-sebastian schmidt-sebastian merged commit 8846f61 into master Jun 24, 2020
@schmidt-sebastian schmidt-sebastian deleted the mrschmidt/retryloop branch June 24, 2020 22:12
@firebase firebase locked and limited conversation to collaborators Jul 25, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants