Skip to content

Commit b0e8253

Browse files
committed
simple_db.ts: change setVersionChangeListener to setDatabaseDeletedListener to be more abstract.
1 parent 0f891d8 commit b0e8253

File tree

5 files changed

+56
-30
lines changed

5 files changed

+56
-30
lines changed

packages/firestore/src/core/firestore_client.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,9 @@ export async function setOfflineComponentProvider(
230230
}
231231
});
232232

233-
// When a user calls clearPersistence() in one client, all other clients
234-
// need to be terminated to allow the delete to succeed.
235-
offlineComponentProvider.persistence.setDatabaseDeletedListener(() =>
236-
client.terminate()
237-
);
233+
offlineComponentProvider.persistence.setDatabaseDeletedListener(() => {
234+
client.terminate();
235+
});
238236

239237
client._offlineComponents = offlineComponentProvider;
240238
}

packages/firestore/src/local/indexeddb_persistence.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { BundleCache } from './bundle_cache';
3131
import { DocumentOverlayCache } from './document_overlay_cache';
3232
import { GlobalsCache } from './globals_cache';
3333
import { IndexManager } from './index_manager';
34+
import { DatabaseDeletedListener } from './persistence';
3435
import { IndexedDbBundleCache } from './indexeddb_bundle_cache';
3536
import { IndexedDbDocumentOverlayCache } from './indexeddb_document_overlay_cache';
3637
import { IndexedDbGlobalsCache } from './indexeddb_globals_cache';
@@ -324,20 +325,25 @@ export class IndexedDbPersistence implements Persistence {
324325
}
325326

326327
/**
327-
* Registers a listener that gets called when the database receives a
328-
* version change event indicating that it has deleted.
328+
* Registers a listener that gets called when the underlying database receives
329+
* an event indicating that it either has been deleted or is pending deletion
330+
* and must be closed.
331+
*
332+
* For example, this callback will be called in the case that multi-tab
333+
* IndexedDB persistence is in use and another tab calls
334+
* clearIndexedDbPersistence(). In that case, this Firestore instance must
335+
* close its IndexedDB connection in order to allow the deletion initiated by
336+
* the other tab to proceed.
337+
*
338+
* This method may only be called once; subsequent invocations will result in
339+
* an exception, refusing to supersede the previously-registered listener.
329340
*
330341
* PORTING NOTE: This is only used for Web multi-tab.
331342
*/
332343
setDatabaseDeletedListener(
333-
databaseDeletedListener: () => Promise<void>
344+
databaseDeletedListener: DatabaseDeletedListener
334345
): void {
335-
this.simpleDb.setVersionChangeListener(async event => {
336-
// Check if an attempt is made to delete IndexedDB.
337-
if (event.newVersion === null) {
338-
await databaseDeletedListener();
339-
}
340-
});
346+
this.simpleDb.setDatabaseDeletedListener(databaseDeletedListener);
341347
}
342348

343349
/**

packages/firestore/src/local/persistence.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ export interface ReferenceDelegate {
9898
): PersistencePromise<void>;
9999
}
100100

101+
export type DatabaseDeletedListener = () => void;
102+
101103
/**
102104
* Persistence is the lowest-level shared interface to persistent storage in
103105
* Firestore.
@@ -151,13 +153,23 @@ export interface Persistence {
151153
shutdown(): Promise<void>;
152154

153155
/**
154-
* Registers a listener that gets called when the database receives a
155-
* version change event indicating that it has deleted.
156+
* Registers a listener that gets called when the underlying database receives
157+
* an event indicating that it either has been deleted or is pending deletion
158+
* and must be closed.
159+
*
160+
* For example, this callback will be called in the case that multi-tab
161+
* IndexedDB persistence is in use and another tab calls
162+
* clearIndexedDbPersistence(). In that case, this Firestore instance must
163+
* close its IndexedDB connection in order to allow the deletion initiated by
164+
* the other tab to proceed.
165+
*
166+
* This method may only be called once; subsequent invocations will result in
167+
* an exception, refusing to supersede the previously-registered listener.
156168
*
157169
* PORTING NOTE: This is only used for Web multi-tab.
158170
*/
159171
setDatabaseDeletedListener(
160-
databaseDeletedListener: () => Promise<void>
172+
databaseDeletedListener: DatabaseDeletedListener
161173
): void;
162174

163175
/**

packages/firestore/src/local/simple_db.ts

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { logDebug, logError } from '../util/log';
2323
import { Deferred } from '../util/promise';
2424

2525
import { PersistencePromise } from './persistence_promise';
26+
import { DatabaseDeletedListener } from './persistence';
2627

2728
// References to `indexedDB` are guarded by SimpleDb.isAvailable() and getGlobal()
2829
/* eslint-disable no-restricted-globals */
@@ -158,8 +159,8 @@ export class SimpleDbTransaction {
158159
*/
159160
export class SimpleDb {
160161
private db?: IDBDatabase;
162+
private databaseDeletedListener?: DatabaseDeletedListener;
161163
private lastClosedDbVersion: number | null = null;
162-
private versionchangelistener?: (event: IDBVersionChangeEvent) => void;
163164

164165
/** Deletes the specified database. */
165166
static delete(name: string): Promise<void> {
@@ -392,22 +393,31 @@ export class SimpleDb {
392393
);
393394
}
394395

395-
if (this.versionchangelistener) {
396-
this.db.onversionchange = event => this.versionchangelistener!(event);
397-
}
396+
this.db.addEventListener(
397+
'versionchange',
398+
event => {
399+
// Notify the listener if another tab attempted to delete the IndexedDb
400+
// database, such as by calling clearIndexedDbPersistence().
401+
if (event.newVersion === null) {
402+
this.databaseDeletedListener?.();
403+
}
404+
},
405+
{ passive: true }
406+
);
398407

399408
return this.db;
400409
}
401410

402-
setVersionChangeListener(
403-
versionChangeListener: (event: IDBVersionChangeEvent) => void
411+
setDatabaseDeletedListener(
412+
databaseDeletedListener: DatabaseDeletedListener
404413
): void {
405-
this.versionchangelistener = versionChangeListener;
406-
if (this.db) {
407-
this.db.onversionchange = (event: IDBVersionChangeEvent) => {
408-
return versionChangeListener(event);
409-
};
414+
if (this.databaseDeletedListener) {
415+
throw new Error(
416+
'setDatabaseDeletedListener() may only be called once, ' +
417+
'and it has already been called'
418+
);
410419
}
420+
this.databaseDeletedListener = databaseDeletedListener;
411421
}
412422

413423
async runTransaction<T>(

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,8 @@ abstract class TestRunner {
365365
this.eventManager.onLastRemoteStoreUnlisten =
366366
triggerRemoteStoreUnlisten.bind(null, this.syncEngine);
367367

368-
await this.persistence.setDatabaseDeletedListener(async () => {
369-
await this.shutdown();
368+
this.persistence.setDatabaseDeletedListener(() => {
369+
this.shutdown();
370370
});
371371

372372
this.started = true;

0 commit comments

Comments
 (0)