Skip to content

Commit 182d100

Browse files
WIP
1 parent 024c2e7 commit 182d100

File tree

4 files changed

+40
-39
lines changed

4 files changed

+40
-39
lines changed

packages/firestore/src/core/firestore_client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ export class FirestoreClient {
394394
if (this.clientTerminated) {
395395
return;
396396
}
397-
this.asyncQueue.enqueueRetryable(() => this.eventMgr.unlisten(listener));
397+
this.asyncQueue.enqueueAndForget(() => this.eventMgr.unlisten(listener));
398398
}
399399

400400
async getDocumentFromLocalCache(

packages/firestore/src/local/local_store.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -911,7 +911,7 @@ class LocalStoreImpl implements LocalStore {
911911
}
912912
}
913913

914-
releaseTarget(
914+
async releaseTarget(
915915
targetId: number,
916916
keepPersistedTargetData: boolean
917917
): Promise<void> {
@@ -922,21 +922,33 @@ class LocalStoreImpl implements LocalStore {
922922
);
923923

924924
const mode = keepPersistedTargetData ? 'readwrite' : 'readwrite-primary';
925-
return this.persistence
926-
.runTransaction('Release target', mode, txn => {
927-
if (!keepPersistedTargetData) {
925+
926+
try {
927+
if (!keepPersistedTargetData) {
928+
await this.persistence.runTransaction('Release target', mode, txn => {
928929
return this.persistence.referenceDelegate.removeTarget(
929930
txn,
930931
targetData!
931932
);
932-
} else {
933-
return PersistencePromise.resolve();
934-
}
935-
})
936-
.then(() => {
937-
this.targetDataByTarget = this.targetDataByTarget.remove(targetId);
938-
this.targetIdByTarget.delete(targetData!.target);
939-
});
933+
});
934+
}
935+
} catch (e) {
936+
if (isIndexedDbTransactionError(e)) {
937+
// If `releaseTarget` fails, we did not advance the sequence
938+
// number for the target. This target might be deleted earlier than
939+
// it otherwise would have, but it should not invalidate the integrity
940+
// of the data.
941+
logDebug(
942+
LOG_TAG,
943+
`Failed to update sequence numbers for target ${targetId}: ${e}`
944+
);
945+
} else {
946+
throw e;
947+
}
948+
}
949+
950+
this.targetDataByTarget = this.targetDataByTarget.remove(targetId);
951+
this.targetIdByTarget.delete(targetData!.target);
940952
}
941953

942954
executeQuery(

packages/firestore/src/remote/remote_store.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -408,18 +408,7 @@ export class RemoteStore implements TargetMetadataProvider {
408408
) {
409409
// There was an error on a target, don't wait for a consistent snapshot
410410
// to raise events
411-
try {
412-
await this.handleTargetError(watchChange);
413-
} catch (e) {
414-
logDebug(
415-
LOG_TAG,
416-
'Failed to remove targets %s: %s ',
417-
watchChange.targetIds.join(','),
418-
e
419-
);
420-
await this.disableNetworkUntilRecovery(e);
421-
}
422-
return;
411+
return this.handleTargetError(watchChange);
423412
}
424413

425414
if (watchChange instanceof DocumentWatchChange) {

packages/firestore/test/unit/specs/recovery_spec.test.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,10 @@ describeSpec('Persistence Recovery', ['no-ios', 'no-android'], () => {
569569
);
570570
});
571571

572-
specTest('Recovers when watch rejection cannot be persisted', [], () => {
572+
specTest('Handles rejections that cannot be persisted', ['exclusive'], () => {
573+
// This test verifies that the client ignores failures during the
574+
// 'Release target' transaction.
575+
573576
const doc1Query = Query.atPath(path('collection/key1'));
574577
const doc2Query = Query.atPath(path('collection/key2'));
575578
const doc1a = doc('collection/key1', 1000, { foo: 'a' });
@@ -593,25 +596,22 @@ describeSpec('Persistence Recovery', ['no-ios', 'no-android'], () => {
593596
doc1Query,
594597
new RpcError(Code.PERMISSION_DENIED, 'Simulated target error')
595598
)
596-
// `failDatabaseTransactions()` causes us to go offline.
597-
.expectActiveTargets()
598-
.expectEvents(doc1Query, { fromCache: true })
599-
.expectEvents(doc2Query, { fromCache: true })
599+
.expectEvents(doc1Query, { errorCode: Code.PERMISSION_DENIED })
600600
.recoverDatabase()
601-
.runTimer(TimerId.AsyncQueueRetry)
602-
.expectActiveTargets(
603-
{ query: doc1Query, resumeToken: 'resume-token-1000' },
604-
{ query: doc2Query, resumeToken: 'resume-token-2000' }
605-
)
606-
.watchAcksFull(doc1Query, 3000)
607-
.expectEvents(doc1Query, {})
608601
.watchRemoves(
609602
doc2Query,
610603
new RpcError(Code.PERMISSION_DENIED, 'Simulated target error')
611604
)
612605
.expectEvents(doc2Query, { errorCode: Code.PERMISSION_DENIED })
613-
.watchSends({ affects: [doc1Query] }, doc1b)
614-
.watchSnapshots(4000)
606+
// Verify that `doc1Query` can be listened to again. Note that the
607+
// resume token is slightly outdated since we failed the final
608+
// target update during the release.
609+
.userListens(doc1Query, 'resume-token-1000')
610+
.expectEvents(doc1Query, {
611+
added: [doc1a],
612+
fromCache: true
613+
})
614+
.watchAcksFull(doc1Query, 4000, doc1b)
615615
.expectEvents(doc1Query, {
616616
modified: [doc1b]
617617
})

0 commit comments

Comments
 (0)