Skip to content

Ignore IndexedDB failure during lease refresh #3020

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 3 commits into from
May 14, 2020

Conversation

schmidt-sebastian
Copy link
Contributor

@schmidt-sebastian schmidt-sebastian commented May 5, 2020

Adresses #2755

@google-oss-bot
Copy link
Contributor

google-oss-bot commented May 5, 2020

Binary Size Report

Affected SDKs

  • @firebase/firestore

    Type Base (575b3fe) Head (27e0693) Diff
    browser 248 kB 248 kB +385 B (+0.2%)
    esm2017 193 kB 194 kB +395 B (+0.2%)
    main 488 kB 489 kB +509 B (+0.1%)
    module 246 kB 246 kB +385 B (+0.2%)
  • firebase

    Type Base (575b3fe) Head (27e0693) Diff
    firebase-firestore.js 287 kB 287 kB +383 B (+0.1%)
    firebase.js 820 kB 820 kB +383 B (+0.0%)

Test Logs

}
if (e.name === 'IndexedDbTransactionError') {
logDebug(LOG_TAG, "Failed to extend owner lease: ", e);
// Proceed in primary mode since the client was not initialized
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is proceeding here assuming we're the primary a useful thing?

When this method is called in the course of enablePersistence, don't we want to report a failure to open the database?

Copy link
Contributor Author

@schmidt-sebastian schmidt-sebastian May 6, 2020

Choose a reason for hiding this comment

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

The idea was to let start() proceed if this check failed. I have now changed the code to fail start() (and hence enablePersistence()) if we get an IndexedDbTransactionError and synchronizeTabs is false.
The fix for this was pretty straightforward, but I ended up changing the callsites to use this.runTransaction instead of this.simpleDb.runTransaction, as this allows me to use MockPersistence to inject failures.

Note that the behavior of this.runTransaction is not all that different: https://github.com/firebase/firebase-js-sdk/blob/master/packages/firestore/src/local/indexeddb_persistence.ts#L808
We make one additional call to verify the lease (which succeeds if no other client has exclusive access). We also obtain access to all ObjectStores, but I think that is not all that different since there is no operation that doesn't also access the DbPrimaryStore.

@wilhuff wilhuff assigned schmidt-sebastian and unassigned wilhuff May 5, 2020
// client startup, we reject the Promise returned by
// `enablePersistence()` and the user can continue to use Firestore
// with in-memory persistence.
// If this fails during a lease refresh, we will instead block the
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems like removing this error here is a regression. Consider:

  • If the client successfully starts
  • goes into the background and loses access to IndexedDB
  • stays in the background for longer than the lease duration

If device comes back online the user opens another tab before our retry has succeeded in refreshing the lease, there's a very real chance we'll lose this race. Users don't even have to be mixing and matching modes for this to fail now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Summary of my last 5 minutes:

  • Gil is wrong.
  • Gil is right.
  • Gil is wrong.
  • Gil is right.
  • Gil it right and wrong.

The idea behind the lease refresh was it would be a "best effort" only operation. If if fails or stalls, any operation to IndexedDB should verify the expected state. That is:

  • "readwrite-primary" operations should verify that the tab has the lease or can become the leaseholder. This already happens.
  • "readwrite", "readonly" operations should verify that they are allowed to access IndexedDB (i.e. there is no primary tab without synchronizeTabs turned on). This is not happening right now. Instead, this is periodically verified via the code that I removed.

So, in conclusion: We should move this verification and run it as part of every transaction. I will leave the code in master and work on this in a separate PR.

@wilhuff wilhuff assigned schmidt-sebastian and unassigned wilhuff May 7, 2020
Copy link
Contributor

@wilhuff wilhuff left a comment

Choose a reason for hiding this comment

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

LGTM

@wilhuff wilhuff assigned schmidt-sebastian and unassigned wilhuff May 14, 2020
@schmidt-sebastian schmidt-sebastian merged commit 2a28a80 into master May 14, 2020
@firebase firebase locked and limited conversation to collaborators Jun 14, 2020
@schmidt-sebastian schmidt-sebastian deleted the mrschmidt/leaserefreshv2 branch November 9, 2020 22:37
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