Skip to content

Commit 13dfc2f

Browse files
Remove Multi-Tab overhead for non-multi-tab persistence (#3362)
1 parent 6f266bf commit 13dfc2f

File tree

9 files changed

+92
-71
lines changed

9 files changed

+92
-71
lines changed

.changeset/late-ladybugs-wash.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
---

packages/firestore/exp/src/api/database.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ import { AsyncQueue } from '../../../src/util/async_queue';
3030
import {
3131
ComponentProvider,
3232
IndexedDbComponentProvider,
33-
MemoryComponentProvider
33+
MemoryComponentProvider,
34+
MultiTabIndexedDbComponentProvider
3435
} from '../../../src/core/component_provider';
3536

3637
import {
@@ -237,8 +238,8 @@ export function enableMultiTabIndexedDbPersistence(
237238
): Promise<void> {
238239
const firestoreImpl = cast(firestore, Firestore);
239240
return firestoreImpl._enablePersistence(
240-
new IndexedDbComponentProvider(),
241-
/*synchronizeTabs=*/ true
241+
new MultiTabIndexedDbComponentProvider(),
242+
/*synchronizeTabs=*/ false
242243
);
243244
}
244245

packages/firestore/exp/test/deps/dependencies.json

+4-19
Original file line numberDiff line numberDiff line change
@@ -8866,11 +8866,6 @@
88668866
"createQueryCache",
88678867
"createRemoteDocumentCache",
88688868
"createRemoteDocumentReadTimeIndex",
8869-
"createWebStorageClientStateKey",
8870-
"createWebStorageMutationBatchKey",
8871-
"createWebStorageOnlineStateKey",
8872-
"createWebStorageQueryTargetMetadataKey",
8873-
"createWebStorageSequenceNumberKey",
88748869
"dbDocumentSize",
88758870
"dbKey",
88768871
"debugAssert",
@@ -8935,7 +8930,6 @@
89358930
"fromVersion",
89368931
"fromWatchChange",
89378932
"fromWatchTargetChangeState",
8938-
"fromWebStorageSequenceNumber",
89398933
"fromWriteResult",
89408934
"fromWriteResults",
89418935
"fullyQualifiedPrefixPath",
@@ -8969,7 +8963,6 @@
89698963
"isPermanentError",
89708964
"isPermanentWriteError",
89718965
"isReferenceValue",
8972-
"isSafeInteger",
89738966
"isServerTimestamp",
89748967
"isValidResourceName",
89758968
"loadProtos",
@@ -8988,8 +8981,6 @@
89888981
"newConnectivityMonitor",
89898982
"newDatastore",
89908983
"newLocalStore",
8991-
"newMultiTabLocalStore",
8992-
"newMultiTabSyncEngine",
89938984
"newPersistentWatchStream",
89948985
"newPersistentWriteStream",
89958986
"newQueryComparator",
@@ -9177,12 +9168,9 @@
91779168
"MemorySharedClientState",
91789169
"MemoryTargetCache",
91799170
"MemoryTransaction",
9180-
"MultiTabLocalStoreImpl",
9181-
"MultiTabSyncEngineImpl",
91829171
"Mutation",
91839172
"MutationBatch",
91849173
"MutationBatchResult",
9185-
"MutationMetadata",
91869174
"MutationResult",
91879175
"NoDocument",
91889176
"NoopConnectivityMonitor",
@@ -9203,10 +9191,8 @@
92039191
"Query",
92049192
"QueryListener",
92059193
"QueryListenersInfo",
9206-
"QueryTargetMetadata",
92079194
"QueryView",
92089195
"ReferenceSet",
9209-
"RemoteClientState",
92109196
"RemoteDocumentChangeBuffer",
92119197
"RemoteEvent",
92129198
"RemoteStore",
@@ -9216,7 +9202,6 @@
92169202
"SchemaConverter",
92179203
"ServerTimestampTransform",
92189204
"SetMutation",
9219-
"SharedOnlineState",
92209205
"SimpleDb",
92219206
"SimpleDbStore",
92229207
"SimpleDbTransaction",
@@ -9243,12 +9228,11 @@
92439228
"View",
92449229
"ViewSnapshot",
92459230
"WatchChangeAggregator",
9246-
"WatchTargetChange",
9247-
"WebStorageSharedClientState"
9231+
"WatchTargetChange"
92489232
],
92499233
"variables": []
92509234
},
9251-
"sizeInBytes": 335737
9235+
"sizeInBytes": 311847
92529236
},
92539237
"enableMultiTabIndexedDbPersistence": {
92549238
"dependencies": {
@@ -9625,6 +9609,7 @@
96259609
"MemorySharedClientState",
96269610
"MemoryTargetCache",
96279611
"MemoryTransaction",
9612+
"MultiTabIndexedDbComponentProvider",
96289613
"MultiTabLocalStoreImpl",
96299614
"MultiTabSyncEngineImpl",
96309615
"Mutation",
@@ -9696,7 +9681,7 @@
96969681
],
96979682
"variables": []
96989683
},
9699-
"sizeInBytes": 335752
9684+
"sizeInBytes": 336213
97009685
},
97019686
"enableNetwork": {
97029687
"dependencies": {

packages/firestore/index.node.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import firebase from '@firebase/app';
1818
import { FirebaseNamespace } from '@firebase/app-types';
1919

2020
import { Firestore } from './src/api/database';
21-
import { IndexedDbComponentProvider } from './src/core/component_provider';
21+
import { MultiTabIndexedDbComponentProvider } from './src/core/component_provider';
2222
import { configureForFirebase } from './src/config';
2323

2424
import './register-module';
@@ -32,7 +32,8 @@ import { name, version } from './package.json';
3232
export function registerFirestore(instance: FirebaseNamespace): void {
3333
configureForFirebase(
3434
instance,
35-
(app, auth) => new Firestore(app, auth, new IndexedDbComponentProvider())
35+
(app, auth) =>
36+
new Firestore(app, auth, new MultiTabIndexedDbComponentProvider())
3637
);
3738
instance.registerVersion(name, version, 'node');
3839
}

packages/firestore/index.rn.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import firebase from '@firebase/app';
1818
import { FirebaseNamespace } from '@firebase/app-types';
1919

2020
import { Firestore } from './src/api/database';
21-
import { IndexedDbComponentProvider } from './src/core/component_provider';
21+
import { MultiTabIndexedDbComponentProvider } from './src/core/component_provider';
2222
import { configureForFirebase } from './src/config';
2323

2424
import './register-module';
@@ -31,7 +31,8 @@ import { name, version } from './package.json';
3131
export function registerFirestore(instance: FirebaseNamespace): void {
3232
configureForFirebase(
3333
instance,
34-
(app, auth) => new Firestore(app, auth, new IndexedDbComponentProvider())
34+
(app, auth) =>
35+
new Firestore(app, auth, new MultiTabIndexedDbComponentProvider())
3536
);
3637
instance.registerVersion(name, version, 'rn');
3738
}

packages/firestore/index.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import firebase from '@firebase/app';
1919
import { FirebaseNamespace } from '@firebase/app-types';
2020

2121
import { Firestore } from './src/api/database';
22-
import { IndexedDbComponentProvider } from './src/core/component_provider';
22+
import { MultiTabIndexedDbComponentProvider } from './src/core/component_provider';
2323
import { configureForFirebase } from './src/config';
2424
import { name, version } from './package.json';
2525

@@ -32,7 +32,8 @@ import './register-module';
3232
export function registerFirestore(instance: FirebaseNamespace): void {
3333
configureForFirebase(
3434
instance,
35-
(app, auth) => new Firestore(app, auth, new IndexedDbComponentProvider())
35+
(app, auth) =>
36+
new Firestore(app, auth, new MultiTabIndexedDbComponentProvider())
3637
);
3738
instance.registerVersion(name, version);
3839
}

packages/firestore/src/core/component_provider.ts

+68-38
Original file line numberDiff line numberDiff line change
@@ -196,52 +196,23 @@ export class MemoryComponentProvider implements ComponentProvider {
196196
export class IndexedDbComponentProvider extends MemoryComponentProvider {
197197
persistence!: IndexedDbPersistence;
198198

199-
// TODO(tree-shaking): Create an IndexedDbComponentProvider and a
200-
// MultiTabComponentProvider. The IndexedDbComponentProvider should depend
201-
// on LocalStore and SyncEngine.
202-
localStore!: MultiTabLocalStore;
203-
syncEngine!: MultiTabSyncEngine;
204-
205-
async initialize(cfg: ComponentConfiguration): Promise<void> {
206-
await super.initialize(cfg);
207-
208-
// NOTE: This will immediately call the listener, so we make sure to
209-
// set it after localStore / remoteStore are started.
210-
await this.persistence.setPrimaryStateListener(async isPrimary => {
211-
await (this.syncEngine as MultiTabSyncEngine).applyPrimaryState(
212-
isPrimary
213-
);
214-
if (this.gcScheduler) {
215-
if (isPrimary && !this.gcScheduler.started) {
216-
this.gcScheduler.start(this.localStore);
217-
} else if (!isPrimary) {
218-
this.gcScheduler.stop();
219-
}
220-
}
221-
});
222-
}
223-
224199
createLocalStore(cfg: ComponentConfiguration): LocalStore {
225-
return newMultiTabLocalStore(
200+
return newLocalStore(
226201
this.persistence,
227202
new IndexFreeQueryEngine(),
228203
cfg.initialUser
229204
);
230205
}
231206

232207
createSyncEngine(cfg: ComponentConfiguration): SyncEngine {
233-
const syncEngine = newMultiTabSyncEngine(
208+
return newSyncEngine(
234209
this.localStore,
235210
this.remoteStore,
236211
cfg.datastore,
237212
this.sharedClientState,
238213
cfg.initialUser,
239214
cfg.maxConcurrentLimboResolutions
240215
);
241-
if (this.sharedClientState instanceof WebStorageSharedClientState) {
242-
this.sharedClientState.syncEngine = syncEngine;
243-
}
244-
return syncEngine;
245216
}
246217

247218
createGarbageCollectionScheduler(
@@ -276,6 +247,72 @@ export class IndexedDbComponentProvider extends MemoryComponentProvider {
276247
);
277248
}
278249

250+
createSharedClientState(cfg: ComponentConfiguration): SharedClientState {
251+
return new MemorySharedClientState();
252+
}
253+
254+
clearPersistence(databaseInfo: DatabaseInfo): Promise<void> {
255+
const persistenceKey = IndexedDbPersistence.buildStoragePrefix(
256+
databaseInfo
257+
);
258+
return IndexedDbPersistence.clearPersistence(persistenceKey);
259+
}
260+
}
261+
262+
/**
263+
* Provides all components needed for Firestore with multi-tab IndexedDB
264+
* persistence.
265+
*
266+
* In the legacy client, this provider is used to provide both multi-tab and
267+
* non-multi-tab persistence since we cannot tell at build time whether
268+
* `synchronizeTabs` will be enabled.
269+
*/
270+
export class MultiTabIndexedDbComponentProvider extends IndexedDbComponentProvider {
271+
localStore!: MultiTabLocalStore;
272+
syncEngine!: MultiTabSyncEngine;
273+
274+
async initialize(cfg: ComponentConfiguration): Promise<void> {
275+
await super.initialize(cfg);
276+
277+
// NOTE: This will immediately call the listener, so we make sure to
278+
// set it after localStore / remoteStore are started.
279+
await this.persistence.setPrimaryStateListener(async isPrimary => {
280+
await (this.syncEngine as MultiTabSyncEngine).applyPrimaryState(
281+
isPrimary
282+
);
283+
if (this.gcScheduler) {
284+
if (isPrimary && !this.gcScheduler.started) {
285+
this.gcScheduler.start(this.localStore);
286+
} else if (!isPrimary) {
287+
this.gcScheduler.stop();
288+
}
289+
}
290+
});
291+
}
292+
293+
createLocalStore(cfg: ComponentConfiguration): LocalStore {
294+
return newMultiTabLocalStore(
295+
this.persistence,
296+
new IndexFreeQueryEngine(),
297+
cfg.initialUser
298+
);
299+
}
300+
301+
createSyncEngine(cfg: ComponentConfiguration): SyncEngine {
302+
const syncEngine = newMultiTabSyncEngine(
303+
this.localStore,
304+
this.remoteStore,
305+
cfg.datastore,
306+
this.sharedClientState,
307+
cfg.initialUser,
308+
cfg.maxConcurrentLimboResolutions
309+
);
310+
if (this.sharedClientState instanceof WebStorageSharedClientState) {
311+
this.sharedClientState.syncEngine = syncEngine;
312+
}
313+
return syncEngine;
314+
}
315+
279316
createSharedClientState(cfg: ComponentConfiguration): SharedClientState {
280317
if (
281318
cfg.persistenceSettings.durable &&
@@ -301,11 +338,4 @@ export class IndexedDbComponentProvider extends MemoryComponentProvider {
301338
}
302339
return new MemorySharedClientState();
303340
}
304-
305-
clearPersistence(databaseInfo: DatabaseInfo): Promise<void> {
306-
const persistenceKey = IndexedDbPersistence.buildStoragePrefix(
307-
databaseInfo
308-
);
309-
return IndexedDbPersistence.clearPersistence(persistenceKey);
310-
}
311341
}

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717

1818
import {
1919
ComponentConfiguration,
20-
IndexedDbComponentProvider,
21-
MemoryComponentProvider
20+
MemoryComponentProvider,
21+
MultiTabIndexedDbComponentProvider
2222
} from '../../../src/core/component_provider';
2323
import {
2424
GarbageCollectionScheduler,
@@ -114,7 +114,7 @@ function failTransactionIfNeeded(
114114
}
115115
}
116116

117-
export class MockIndexedDbComponentProvider extends IndexedDbComponentProvider {
117+
export class MockIndexedDbComponentProvider extends MultiTabIndexedDbComponentProvider {
118118
persistence!: MockIndexedDbPersistence;
119119

120120
constructor(

packages/firestore/test/util/api_helpers.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
Query,
2727
QuerySnapshot
2828
} from '../../src/api/database';
29-
import { IndexedDbComponentProvider } from '../../src/core/component_provider';
29+
import { MultiTabIndexedDbComponentProvider } from '../../src/core/component_provider';
3030
import { Query as InternalQuery } from '../../src/core/query';
3131
import {
3232
ChangeType,
@@ -49,7 +49,7 @@ export const FIRESTORE = new Firestore(
4949
database: '(default)'
5050
},
5151
new Provider('auth-internal', new ComponentContainer('default')),
52-
new IndexedDbComponentProvider()
52+
new MultiTabIndexedDbComponentProvider()
5353
);
5454

5555
export function firestore(): Firestore {

0 commit comments

Comments
 (0)