Skip to content

Commit a926099

Browse files
Reduce diff
1 parent 5902cb8 commit a926099

File tree

8 files changed

+101
-127
lines changed

8 files changed

+101
-127
lines changed

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ import {
3232
MemoryOfflineComponentProvider,
3333
OfflineComponentProvider,
3434
IndexedDbOfflineComponentProvider,
35-
MultiTabOfflineComponentProvider,
36-
MultiTabOnlineComponentProvider
35+
MultiTabOfflineComponentProvider
3736
} from '../../../src/core/component_provider';
3837

3938
import {
@@ -250,9 +249,13 @@ export function enableMultiTabIndexedDbPersistence(
250249
firestore: firestore.FirebaseFirestore
251250
): Promise<void> {
252251
const firestoreImpl = cast(firestore, Firestore);
252+
const onlineComponentProvider = new OnlineComponentProvider();
253+
const offlineComponentProvider = new MultiTabOfflineComponentProvider(
254+
onlineComponentProvider
255+
);
253256
return firestoreImpl._enablePersistence(
254-
new MultiTabOfflineComponentProvider(),
255-
new MultiTabOnlineComponentProvider(),
257+
offlineComponentProvider,
258+
onlineComponentProvider,
256259
/*synchronizeTabs=*/ false
257260
);
258261
}

packages/firestore/index.node.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { FirebaseNamespace } from '@firebase/app-types';
1919

2020
import { Firestore } from './src/api/database';
2121
import {
22-
MultiTabOfflineComponentProvider, MultiTabOnlineComponentProvider
22+
MultiTabOfflineComponentProvider,OnlineComponentProvider
2323
} from './src/core/component_provider';
2424
import { configureForFirebase } from './src/config';
2525

@@ -32,14 +32,18 @@ import { name, version } from './package.json';
3232
* Persistence can be enabled via `firebase.firestore().enablePersistence()`.
3333
*/
3434
export function registerFirestore(instance: FirebaseNamespace): void {
35+
const onlineComponentProvider =
36+
new OnlineComponentProvider();
37+
const offlineComponentProvider =
38+
new MultiTabOfflineComponentProvider(onlineComponentProvider);
3539
configureForFirebase(
3640
instance,
3741
(app, auth) =>
3842
new Firestore(
3943
app,
4044
auth,
41-
new MultiTabOfflineComponentProvider(),
42-
new MultiTabOnlineComponentProvider()
45+
offlineComponentProvider,
46+
onlineComponentProvider
4347
)
4448
);
4549
instance.registerVersion(name, version, 'node');

packages/firestore/index.rn.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { FirebaseNamespace } from '@firebase/app-types';
2020
import { Firestore } from './src/api/database';
2121
import {
2222
MultiTabOfflineComponentProvider,
23-
MultiTabOnlineComponentProvider
23+
OnlineComponentProvider
2424
} from './src/core/component_provider';
2525
import { configureForFirebase } from './src/config';
2626

@@ -32,14 +32,19 @@ import { name, version } from './package.json';
3232
* Persistence can be enabled via `firebase.firestore().enablePersistence()`.
3333
*/
3434
export function registerFirestore(instance: FirebaseNamespace): void {
35+
36+
const onlineComponentProvider =
37+
new OnlineComponentProvider();
38+
const offlineComponentProvider =
39+
new MultiTabOfflineComponentProvider(onlineComponentProvider);
3540
configureForFirebase(
3641
instance,
3742
(app, auth) =>
3843
new Firestore(
3944
app,
4045
auth,
41-
new MultiTabOfflineComponentProvider(),
42-
new MultiTabOnlineComponentProvider()
46+
offlineComponentProvider,
47+
onlineComponentProvider
4348
)
4449
);
4550
instance.registerVersion(name, version, 'rn');

packages/firestore/index.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { FirebaseNamespace } from '@firebase/app-types';
2020

2121
import { Firestore } from './src/api/database';
2222
import {
23-
MultiTabOfflineComponentProvider, MultiTabOnlineComponentProvider
23+
MultiTabOfflineComponentProvider, OnlineComponentProvider
2424
} from './src/core/component_provider';
2525
import { configureForFirebase } from './src/config';
2626
import { name, version } from './package.json';
@@ -32,14 +32,18 @@ import './register-module';
3232
* Persistence can be enabled via `firebase.firestore().enablePersistence()`.
3333
*/
3434
export function registerFirestore(instance: FirebaseNamespace): void {
35+
const onlineComponentProvider =
36+
new OnlineComponentProvider();
37+
const offlineComponentProvider =
38+
new MultiTabOfflineComponentProvider(onlineComponentProvider);
3539
configureForFirebase(
3640
instance,
3741
(app, auth) =>
3842
new Firestore(
3943
app,
4044
auth,
41-
new MultiTabOfflineComponentProvider(),
42-
new MultiTabOnlineComponentProvider()
45+
offlineComponentProvider,
46+
onlineComponentProvider
4347
)
4448
);
4549
instance.registerVersion(name, version);

packages/firestore/src/core/component_provider.ts

Lines changed: 50 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import { newSerializer } from '../platform/serializer';
6262
import { getDocument, getWindow } from '../platform/dom';
6363
import { CredentialsProvider } from '../api/credentials';
6464
import { Connection } from '../remote/connection';
65+
import { SharedClientStateSyncer } from '../local/shared_client_state_syncer';
6566

6667
const MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE =
6768
'You are using the memory-only build of Firestore. Persistence support is ' +
@@ -229,6 +230,49 @@ export class IndexedDbOfflineComponentProvider extends MemoryOfflineComponentPro
229230
* `synchronizeTabs` will be enabled.
230231
*/
231232
export class MultiTabOfflineComponentProvider extends IndexedDbOfflineComponentProvider {
233+
constructor(
234+
private readonly onlineComponentProvider: OnlineComponentProvider
235+
) {
236+
super();
237+
}
238+
239+
async initialize(cfg: ComponentConfiguration): Promise<void> {
240+
await super.initialize(cfg);
241+
242+
await this.onlineComponentProvider.initialize(this, cfg);
243+
const syncEngine = this.onlineComponentProvider.syncEngine;
244+
245+
if (this.sharedClientState instanceof WebStorageSharedClientState) {
246+
this.sharedClientState.syncEngine = {
247+
applyBatchState: applyBatchState.bind(null, syncEngine),
248+
applyTargetState: applyTargetState.bind(null, syncEngine),
249+
applyActiveTargetsChange: applyActiveTargetsChange.bind(
250+
null,
251+
syncEngine
252+
),
253+
getActiveClients: getActiveClients.bind(null, syncEngine)
254+
};
255+
256+
await this.sharedClientState.start();
257+
}
258+
259+
// NOTE: This will immediately call the listener, so we make sure to
260+
// set it after localStore / remoteStore are started.
261+
await this.persistence.setPrimaryStateListener(async isPrimary => {
262+
await applyPrimaryState(
263+
this.onlineComponentProvider.syncEngine,
264+
isPrimary
265+
);
266+
if (this.gcScheduler) {
267+
if (isPrimary && !this.gcScheduler.started) {
268+
this.gcScheduler.start(this.localStore);
269+
} else if (!isPrimary) {
270+
this.gcScheduler.stop();
271+
}
272+
}
273+
});
274+
}
275+
232276
createSharedClientState(cfg: ComponentConfiguration): SharedClientState {
233277
if (
234278
cfg.persistenceSettings.durable &&
@@ -273,6 +317,11 @@ export class OnlineComponentProvider {
273317
offlineComponentProvider: OfflineComponentProvider,
274318
cfg: ComponentConfiguration
275319
): Promise<void> {
320+
if (this.datastore) {
321+
// OnlineComponentProvider may get initialized multiple times if MultiTabPersistence is used.
322+
return;
323+
}
324+
276325
this.localStore = offlineComponentProvider.localStore;
277326
this.sharedClientState = offlineComponentProvider.sharedClientState;
278327
this.datastore = this.createDatastore(cfg);
@@ -288,6 +337,7 @@ export class OnlineComponentProvider {
288337
onlineState,
289338
OnlineStateSource.SharedClientState
290339
);
340+
291341
this.remoteStore.syncEngine = this.syncEngine;
292342

293343
await this.remoteStore.start();
@@ -334,60 +384,3 @@ export class OnlineComponentProvider {
334384
);
335385
}
336386
}
337-
338-
/**
339-
* Initializes and wires the components that are needed to interface with the
340-
* network and registers callbacks needed for multi-tab persistence.
341-
*/
342-
export class MultiTabOnlineComponentProvider extends OnlineComponentProvider {
343-
async initialize(
344-
offlineComponentProvider: OfflineComponentProvider,
345-
cfg: ComponentConfiguration
346-
): Promise<void> {
347-
await super.initialize(offlineComponentProvider, cfg);
348-
if (
349-
cfg.persistenceSettings.durable &&
350-
cfg.persistenceSettings.synchronizeTabs
351-
) {
352-
const sharedClientState = debugCast(
353-
offlineComponentProvider.sharedClientState,
354-
WebStorageSharedClientState
355-
);
356-
const persistence = debugCast(
357-
offlineComponentProvider.persistence,
358-
IndexedDbPersistence
359-
);
360-
const syncEngine = this.syncEngine;
361-
362-
sharedClientState.syncEngine = {
363-
applyBatchState: applyBatchState.bind(null, syncEngine),
364-
applyTargetState: applyTargetState.bind(null, syncEngine),
365-
applyActiveTargetsChange: applyActiveTargetsChange.bind(
366-
null,
367-
syncEngine
368-
),
369-
getActiveClients: getActiveClients.bind(null, syncEngine)
370-
};
371-
372-
// TODO(firestorexp): Should we support offline-only Multi-Tab? This would
373-
// likely mean that most methods from in the SharedClientState callback can
374-
// no longer rely on sync engine,
375-
await sharedClientState.start();
376-
377-
// NOTE: This will immediately call the listener, so we make sure to
378-
// set it after localStore / remoteStore are started.
379-
await persistence.setPrimaryStateListener(async isPrimary => {
380-
await applyPrimaryState(syncEngine, isPrimary);
381-
if (offlineComponentProvider.gcScheduler) {
382-
if (isPrimary && !offlineComponentProvider.gcScheduler.started) {
383-
offlineComponentProvider.gcScheduler.start(
384-
offlineComponentProvider.localStore
385-
);
386-
} else if (!isPrimary) {
387-
offlineComponentProvider.gcScheduler.stop();
388-
}
389-
}
390-
});
391-
}
392-
}
393-
}

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

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ import {
1919
ComponentConfiguration,
2020
MemoryOfflineComponentProvider,
2121
OnlineComponentProvider,
22-
MultiTabOfflineComponentProvider,
23-
MultiTabOnlineComponentProvider
22+
MultiTabOfflineComponentProvider
2423
} from '../../../src/core/component_provider';
2524
import {
2625
GarbageCollectionScheduler,
@@ -138,31 +137,15 @@ export class MockOnlineComponentProvider extends OnlineComponentProvider {
138137
}
139138
}
140139

141-
export class MockMultiTabOnlineComponentProvider extends MultiTabOnlineComponentProvider {
142-
connection!: MockConnection;
143-
144-
async loadConnection(cfg: ComponentConfiguration): Promise<Connection> {
145-
this.connection = new MockConnection(cfg.asyncQueue);
146-
return this.connection;
147-
}
148-
149-
createDatastore(cfg: ComponentConfiguration): Datastore {
150-
const serializer = new JsonProtoSerializer(
151-
cfg.databaseInfo.databaseId,
152-
/* useProto3Json= */ true
153-
);
154-
return newDatastore(cfg.credentials, serializer);
155-
}
156-
}
157-
158140
export class MockMultiTabOfflineComponentProvider extends MultiTabOfflineComponentProvider {
159141
persistence!: MockIndexedDbPersistence;
160142

161143
constructor(
162144
private readonly window: WindowLike,
163-
private readonly document: FakeDocument
145+
private readonly document: FakeDocument,
146+
onlineComponentProvider: OnlineComponentProvider
164147
) {
165-
super();
148+
super(onlineComponentProvider);
166149
}
167150

168151
createGarbageCollectionScheduler(

0 commit comments

Comments
 (0)