Skip to content

Commit fc37f4c

Browse files
author
Greg Soltis
authored
Stop starting the remote document cache (#1116)
* Stop starting the remote document cache * Review feedback * MultiTab -> MultiClient
1 parent d559e80 commit fc37f4c

10 files changed

+118
-80
lines changed

packages/firestore/src/core/firestore_client.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,8 @@ export class FirestoreClient {
307307
this.clientId,
308308
this.platform,
309309
this.asyncQueue,
310-
serializer
310+
serializer,
311+
settings.experimentalTabSynchronization
311312
);
312313
this.persistence = persistence;
313314

@@ -330,7 +331,7 @@ export class FirestoreClient {
330331
user
331332
)
332333
: new MemorySharedClientState();
333-
return persistence.start(settings.experimentalTabSynchronization);
334+
return persistence.start();
334335
});
335336
}
336337

packages/firestore/src/local/indexeddb_persistence.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -209,22 +209,27 @@ export class IndexedDbPersistence implements Persistence {
209209
private readonly clientId: ClientId,
210210
platform: Platform,
211211
private readonly queue: AsyncQueue,
212-
serializer: JsonProtoSerializer
212+
serializer: JsonProtoSerializer,
213+
synchronizeTabs: boolean
213214
) {
214215
this.dbName = persistenceKey + IndexedDbPersistence.MAIN_DATABASE;
215216
this.serializer = new LocalSerializer(serializer);
216217
this.document = platform.document;
217218
this.window = platform.window;
219+
this.allowTabSynchronization = synchronizeTabs;
220+
this.queryCache = new IndexedDbQueryCache(this.serializer);
221+
this.remoteDocumentCache = new IndexedDbRemoteDocumentCache(
222+
this.serializer,
223+
/*keepDocumentChangeLog=*/ this.allowTabSynchronization
224+
);
218225
}
219226

220227
/**
221228
* Attempt to start IndexedDb persistence.
222229
*
223-
* @param {boolean} synchronizeTabs Whether to enable shared persistence
224-
* across multiple tabs.
225230
* @return {Promise<void>} Whether persistence was enabled.
226231
*/
227-
start(synchronizeTabs?: boolean): Promise<void> {
232+
start(): Promise<void> {
228233
if (!IndexedDbPersistence.isAvailable()) {
229234
this.persistenceError = new FirestoreError(
230235
Code.UNIMPLEMENTED,
@@ -234,19 +239,13 @@ export class IndexedDbPersistence implements Persistence {
234239
}
235240

236241
assert(!this.started, 'IndexedDbPersistence double-started!');
237-
this.allowTabSynchronization = !!synchronizeTabs;
238-
239242
assert(this.window !== null, "Expected 'window' to be defined");
240243

241244
return SimpleDb.openOrCreate(this.dbName, SCHEMA_VERSION, createOrUpgradeDb)
242245
.then(db => {
243246
this.simpleDb = db;
244-
this.queryCache = new IndexedDbQueryCache(this.serializer);
245-
this.remoteDocumentCache = new IndexedDbRemoteDocumentCache(
246-
this.serializer,
247-
/*keepDocumentChangeLog=*/ this.allowTabSynchronization
248-
);
249247
})
248+
.then(() => this.startRemoteDocumentCache())
250249
.then(() => {
251250
this.attachVisibilityHandler();
252251
this.attachWindowUnloadHook();
@@ -259,6 +258,12 @@ export class IndexedDbPersistence implements Persistence {
259258
});
260259
}
261260

261+
private startRemoteDocumentCache(): Promise<void> {
262+
return this.simpleDb.runTransaction('readonly', ALL_STORES, txn =>
263+
this.remoteDocumentCache.start(txn)
264+
);
265+
}
266+
262267
setPrimaryStateListener(
263268
primaryStateListener: PrimaryStateListener
264269
): Promise<void> {

packages/firestore/src/local/indexeddb_remote_document_cache.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import { PersistencePromise } from './persistence_promise';
3838
import { RemoteDocumentCache } from './remote_document_cache';
3939
import { SnapshotVersion } from '../core/snapshot_version';
4040
import { assert } from '../util/assert';
41-
import { SimpleDbStore } from './simple_db';
41+
import { SimpleDb, SimpleDbStore, SimpleDbTransaction } from './simple_db';
4242

4343
export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache {
4444
/** The last id read by `getNewDocumentChanges()`. */
@@ -60,12 +60,24 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache {
6060
return this._lastProcessedDocumentChangeId;
6161
}
6262

63-
start(transaction: PersistenceTransaction): PersistencePromise<void> {
63+
/**
64+
* Starts up the remote document cache.
65+
*
66+
* Reads the ID of the last document change from the documentChanges store.
67+
* Existing changes will not be returned as part of
68+
* `getNewDocumentChanges()`.
69+
*/
70+
// PORTING NOTE: This is only used for multi-tab synchronization.
71+
start(transaction: SimpleDbTransaction): PersistencePromise<void> {
6472
// If there are no existing changes, we set `lastProcessedDocumentChangeId`
6573
// to 0 since IndexedDb's auto-generated keys start at 1.
6674
this._lastProcessedDocumentChangeId = 0;
6775

68-
return documentChangesStore(transaction).iterate(
76+
const store = SimpleDb.getStore<
77+
DbRemoteDocumentChangesKey,
78+
DbRemoteDocumentChanges
79+
>(transaction, DbRemoteDocumentChanges.store);
80+
return store.iterate(
6981
{ keysOnly: true, reverse: true },
7082
(key, value, control) => {
7183
this._lastProcessedDocumentChangeId = key;

packages/firestore/src/local/local_store.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,9 @@ export class LocalStore {
203203
/** Performs any initial startup actions required by the local store. */
204204
start(): Promise<void> {
205205
// TODO(multitab): Ensure that we in fact don't need the primary lease.
206-
return this.persistence.runTransaction('Start LocalStore', false, txn => {
207-
return this.startMutationQueue(txn).next(() =>
208-
this.startRemoteDocumentCache(txn)
209-
);
210-
});
206+
return this.persistence.runTransaction('Start LocalStore', false, txn =>
207+
this.startMutationQueue(txn)
208+
);
211209
}
212210

213211
/**
@@ -312,12 +310,6 @@ export class LocalStore {
312310
});
313311
}
314312

315-
private startRemoteDocumentCache(
316-
txn: PersistenceTransaction
317-
): PersistencePromise<void> {
318-
return this.remoteDocuments.start(txn);
319-
}
320-
321313
/* Accept locally generated Mutations and commit them to storage. */
322314
localWrite(mutations: Mutation[]): Promise<LocalWriteResult> {
323315
return this.persistence.runTransaction(

packages/firestore/src/local/remote_document_cache.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,6 @@ import { PersistencePromise } from './persistence_promise';
3131
* known to not exist).
3232
*/
3333
export interface RemoteDocumentCache {
34-
/**
35-
* Starts up the remote document cache.
36-
*
37-
* Reads the ID of the last document change from the documentChanges store.
38-
* Existing changes will not be returned as part of
39-
* `getNewDocumentChanges()`.
40-
*/
41-
// PORTING NOTE: This is only used for multi-tab synchronization.
42-
start(transaction: PersistenceTransaction): PersistencePromise<void>;
43-
4434
/**
4535
* Adds or replaces document entries in the cache.
4636
*

packages/firestore/test/unit/local/indexeddb_persistence.test.ts

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import { PlatformSupport } from '../../../src/platform/platform';
4141
import { AsyncQueue } from '../../../src/util/async_queue';
4242
import { SharedFakeWebStorage, TestPlatform } from '../../util/test_platform';
4343
import { SnapshotVersion } from '../../../src/core/snapshot_version';
44+
import { PersistenceSettings } from '../../../src/api/database';
4445

4546
const INDEXEDDB_TEST_DATABASE_PREFIX = 'schemaTest/';
4647
const INDEXEDDB_TEST_DATABASE =
@@ -77,8 +78,9 @@ function withDb(
7778
});
7879
}
7980

80-
async function withPersistence(
81+
async function withCustomPersistence(
8182
clientId: ClientId,
83+
settings: PersistenceSettings,
8284
fn: (
8385
persistence: IndexedDbPersistence,
8486
platform: TestPlatform,
@@ -100,13 +102,46 @@ async function withPersistence(
100102
clientId,
101103
platform,
102104
queue,
103-
serializer
105+
serializer,
106+
settings.experimentalTabSynchronization
104107
);
105108

106109
await fn(persistence, platform, queue);
107110
await persistence.shutdown();
108111
}
109112

113+
async function withPersistence(
114+
clientId: ClientId,
115+
fn: (
116+
persistence: IndexedDbPersistence,
117+
platform: TestPlatform,
118+
queue: AsyncQueue
119+
) => Promise<void>
120+
): Promise<void> {
121+
return withCustomPersistence(
122+
clientId,
123+
new PersistenceSettings(/* enabled */ true),
124+
fn
125+
);
126+
}
127+
128+
async function withMultiClientPersistence(
129+
clientId: ClientId,
130+
fn: (
131+
persistence: IndexedDbPersistence,
132+
platform: TestPlatform,
133+
queue: AsyncQueue
134+
) => Promise<void>
135+
): Promise<void> {
136+
return withCustomPersistence(
137+
clientId,
138+
new PersistenceSettings(/* enabled */ true, {
139+
experimentalTabSynchronization: true
140+
}),
141+
fn
142+
);
143+
}
144+
110145
function getAllObjectStores(db: IDBDatabase): string[] {
111146
const objectStores: string[] = [];
112147
for (let i = 0; i < db.objectStoreNames.length; ++i) {
@@ -427,22 +462,20 @@ describe('IndexedDb: allowTabSynchronization', () => {
427462

428463
it('rejects access when synchronization is disabled', () => {
429464
return withPersistence('clientA', async db1 => {
430-
await db1.start(/*synchronizeTabs=*/ false);
465+
await db1.start();
431466
await withPersistence('clientB', async db2 => {
432-
await expect(
433-
db2.start(/*synchronizeTabs=*/ false)
434-
).to.eventually.be.rejectedWith(
467+
await expect(db2.start()).to.eventually.be.rejectedWith(
435468
'There is another tab open with offline persistence enabled.'
436469
);
437470
});
438471
});
439472
});
440473

441474
it('grants access when synchronization is enabled', async () => {
442-
return withPersistence('clientA', async db1 => {
443-
await db1.start(/*synchronizeTabs=*/ true);
444-
await withPersistence('clientB', async db2 => {
445-
await db2.start(/*synchronizeTabs=*/ true);
475+
return withMultiClientPersistence('clientA', async db1 => {
476+
await db1.start();
477+
await withMultiClientPersistence('clientB', async db2 => {
478+
await db2.start();
446479
});
447480
});
448481
});

packages/firestore/test/unit/local/persistence_test_helpers.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,10 @@ export async function testIndexedDbPersistence(
7272
clientId,
7373
platform,
7474
queue,
75-
serializer
75+
serializer,
76+
options.synchronizeTabs
7677
);
77-
await persistence.start(options.synchronizeTabs);
78+
await persistence.start();
7879
return persistence;
7980
}
8081

packages/firestore/test/unit/local/remote_document_cache.test.ts

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ import * as persistenceHelpers from './persistence_test_helpers';
3232
import { TestRemoteDocumentCache } from './test_remote_document_cache';
3333
import { MaybeDocumentMap } from '../../../src/model/collections';
3434
import { IndexedDbRemoteDocumentCache } from '../../../src/local/indexeddb_remote_document_cache';
35+
import {
36+
DbRemoteDocumentChangesKey,
37+
DbRemoteDocumentChanges
38+
} from '../../../src/local/indexeddb_schema';
3539

3640
// Helpers for use throughout tests.
3741
const DOC_PATH = 'a/b';
@@ -78,27 +82,41 @@ describe('IndexedDbRemoteDocumentCache', () => {
7882
.next(() => cache.removeDocumentChangesThroughChangeId(txn, 1));
7983
}
8084
);
85+
// We removed the first batch, there should be a single batch remaining.
86+
const remainingChangeCount = await persistence.runTransaction(
87+
'verify',
88+
true,
89+
txn => {
90+
const store = IndexedDbPersistence.getStore<
91+
DbRemoteDocumentChangesKey,
92+
DbRemoteDocumentChanges
93+
>(txn, DbRemoteDocumentChanges.store);
94+
return store.count();
95+
}
96+
);
97+
expect(remainingChangeCount).to.equal(1);
98+
});
99+
100+
it('skips previous changes', async () => {
101+
// Add a document to simulate a previous run.
102+
let cache = new TestRemoteDocumentCache(
103+
persistence,
104+
persistence.getRemoteDocumentCache()
105+
);
106+
await cache.addEntries([doc('a/1', 1, DOC_DATA)]);
81107
await persistence.shutdown(/* deleteData= */ false);
82108

83-
// Now make sure that we can only read back the second batch.
109+
// Start a new run of the persistence layer
84110
persistence = await persistenceHelpers.testIndexedDbPersistence({
85111
synchronizeTabs: true,
86112
dontPurgeData: true
87113
});
88-
89-
// Note that we don't call `start()` on the RemoteDocumentCache. If we did,
90-
// the cache would only replay changes that were added after invoking
91-
// start().
92-
const changedDocs = await persistence.runTransaction(
93-
'getNewDocumentChanges',
94-
false,
95-
txn => {
96-
const cache = persistence.getRemoteDocumentCache();
97-
return cache.getNewDocumentChanges(txn);
98-
}
114+
cache = new TestRemoteDocumentCache(
115+
persistence,
116+
persistence.getRemoteDocumentCache()
99117
);
100-
101-
assertMatches([doc('c/1', 3, DOC_DATA)], changedDocs);
118+
const changedDocs = await cache.getNextDocumentChanges();
119+
assertMatches([], changedDocs);
102120
});
103121

104122
genericRemoteDocumentCacheTests();
@@ -233,15 +251,6 @@ function genericRemoteDocumentCacheTests(): void {
233251
changedDocs
234252
);
235253
});
236-
237-
it('start() skips previous changes', async () => {
238-
await cache.addEntries([doc('a/1', 1, DOC_DATA)]);
239-
240-
await cache.start();
241-
242-
const changedDocs = await cache.getNextDocumentChanges();
243-
assertMatches([], changedDocs);
244-
});
245254
}
246255

247256
function assertMatches(

packages/firestore/test/unit/local/test_remote_document_cache.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,6 @@ export class TestRemoteDocumentCache {
3131
public cache: RemoteDocumentCache
3232
) {}
3333

34-
start(): Promise<void> {
35-
return this.persistence.runTransaction('start', false, txn => {
36-
return this.cache.start(txn);
37-
});
38-
}
39-
4034
addEntries(maybeDocuments: MaybeDocument[]): Promise<void> {
4135
return this.persistence.runTransaction('addEntry', true, txn => {
4236
return this.cache.addEntries(txn, maybeDocuments);

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,9 +1184,10 @@ class IndexedDbTestRunner extends TestRunner {
11841184
this.clientId,
11851185
this.platform,
11861186
this.queue,
1187-
serializer
1187+
serializer,
1188+
/*synchronizeTabs=*/ true
11881189
);
1189-
await persistence.start(/*synchronizeTabs=*/ true);
1190+
await persistence.start();
11901191
return persistence;
11911192
}
11921193

0 commit comments

Comments
 (0)