-
Notifications
You must be signed in to change notification settings - Fork 938
IndexedDB recovery for waitForPendingWrites() #3038
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
Changes from 2 commits
0852c5d
8f47d7a
a0eb1df
d68d8d1
001cf9c
ae2fa31
8bc241f
d09a3a3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,11 @@ | |
import { ListenSequence } from '../core/listen_sequence'; | ||
import { ListenSequenceNumber, TargetId } from '../core/types'; | ||
import { debugAssert } from '../util/assert'; | ||
import { AsyncQueue, TimerId } from '../util/async_queue'; | ||
import { | ||
AsyncQueue, | ||
TimerId, | ||
executeWithIndexedDbRecovery | ||
} from '../util/async_queue'; | ||
import { getLogLevel, logDebug, LogLevel } from '../util/log'; | ||
import { primitiveComparator } from '../util/misc'; | ||
import { CancelablePromise } from '../util/promise'; | ||
|
@@ -32,8 +36,6 @@ import { | |
import { PersistencePromise } from './persistence_promise'; | ||
import { TargetData } from './target_data'; | ||
|
||
const LOG_TAG = 'LruGarbageCollector'; | ||
|
||
/** | ||
* Persistence layers intending to use LRU Garbage collection should have reference delegates that | ||
* implement this interface. This interface defines the operations that the LRU garbage collector | ||
|
@@ -267,23 +269,15 @@ export class LruScheduler implements GarbageCollectionScheduler { | |
this.gcTask = this.asyncQueue.enqueueAfterDelay( | ||
TimerId.LruGarbageCollection, | ||
delay, | ||
async () => { | ||
() => { | ||
this.gcTask = null; | ||
this.hasRun = true; | ||
try { | ||
await localStore.collectGarbage(this.garbageCollector); | ||
} catch (e) { | ||
if (e.name === 'IndexedDbTransactionError') { | ||
logDebug( | ||
LOG_TAG, | ||
'Ignoring IndexedDB error during garbage collection: ', | ||
e | ||
); | ||
} else { | ||
await ignoreIfPrimaryLeaseLoss(e); | ||
} | ||
} | ||
await this.scheduleGC(localStore); | ||
return executeWithIndexedDbRecovery( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In particular, this change has fairly significantly harmed this method:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is now reverted, but there are some arguments for using Promise chains here:
|
||
() => localStore.collectGarbage(this.garbageCollector).then(() => {}), | ||
/* recoveryHandler= */ () => {} | ||
) | ||
.then(() => this.scheduleGC(localStore)) | ||
.catch(ignoreIfPrimaryLeaseLoss); | ||
} | ||
); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't say this pattern is really different from
try
/catch
, except it's hiding that.What do you think of the more direct:
As I see it:
IndexedDbTransactionError
typeBuilding on this, you could actually cut the verbosity of each call down by making a
checkRecoverable
that takes the message, logs it, and then throws if unrecoverable or returns theFirestoreError
if it is?The catch blocks would look like:
The implementation would look like:
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried really hard to somehow push the try/catch into my helper, but it might have been a bit too mush. I updated the PR to use a helper that returns a FirestoreError if the error is an IndexedDB error, otherwise it throws.