Skip to content

Commit 2fca6eb

Browse files
author
Greg Soltis
authored
Internal persistence settings (#1411)
* Refactor PersistenceSettings
1 parent 50a7af6 commit 2fca6eb

File tree

3 files changed

+46
-85
lines changed

3 files changed

+46
-85
lines changed

packages/firestore/src/api/database.ts

+17-41
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ import { FirebaseApp } from '@firebase/app-types';
2020
import { FirebaseService } from '@firebase/app-types/private';
2121
import { DatabaseId, DatabaseInfo } from '../core/database_info';
2222
import { ListenOptions } from '../core/event_manager';
23-
import { FirestoreClient } from '../core/firestore_client';
23+
import {
24+
FirestoreClient,
25+
IndexedDbPersistenceSettings,
26+
InternalPersistenceSettings,
27+
MemoryPersistenceSettings
28+
} from '../core/firestore_client';
2429
import {
2530
Bound,
2631
Direction,
@@ -237,38 +242,6 @@ class FirestoreConfig {
237242
persistence: boolean;
238243
}
239244

240-
/**
241-
* Encapsulates the settings that can be used to configure Firestore
242-
* persistence.
243-
*/
244-
export class PersistenceSettings {
245-
/** Whether to enable multi-tab synchronization. */
246-
experimentalTabSynchronization: boolean;
247-
248-
constructor(
249-
readonly enabled: boolean,
250-
settings?: firestore.PersistenceSettings
251-
) {
252-
assert(
253-
enabled || !settings,
254-
'Can only provide PersistenceSettings with persistence enabled'
255-
);
256-
settings = settings || {};
257-
this.experimentalTabSynchronization = objUtils.defaulted(
258-
settings.experimentalTabSynchronization,
259-
DEFAULT_SYNCHRONIZE_TABS
260-
);
261-
}
262-
263-
isEqual(other: PersistenceSettings): boolean {
264-
return (
265-
this.enabled === other.enabled &&
266-
this.experimentalTabSynchronization ===
267-
other.experimentalTabSynchronization
268-
);
269-
}
270-
}
271-
272245
/**
273246
* The root reference to the database.
274247
*/
@@ -371,23 +344,29 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
371344
'any other methods on a Firestore object.'
372345
);
373346
}
374-
375347
return this.configureClient(
376-
new PersistenceSettings(/* enabled= */ true, settings)
348+
new IndexedDbPersistenceSettings(
349+
this._config.settings.cacheSizeBytes,
350+
settings !== undefined &&
351+
objUtils.defaulted(
352+
settings.experimentalTabSynchronization,
353+
DEFAULT_SYNCHRONIZE_TABS
354+
)
355+
)
377356
);
378357
}
379358

380359
ensureClientConfigured(): FirestoreClient {
381360
if (!this._firestoreClient) {
382361
// Kick off starting the client but don't actually wait for it.
383362
// tslint:disable-next-line:no-floating-promises
384-
this.configureClient(new PersistenceSettings(/* enabled= */ false));
363+
this.configureClient(new MemoryPersistenceSettings());
385364
}
386365
return this._firestoreClient as FirestoreClient;
387366
}
388367

389368
private configureClient(
390-
persistenceSettings: PersistenceSettings
369+
persistenceSettings: InternalPersistenceSettings
391370
): Promise<void> {
392371
assert(
393372
!!this._config.settings.host,
@@ -454,10 +433,7 @@ follow these steps, YOUR APP MAY BREAK.`);
454433
this._config.credentials,
455434
this._queue
456435
);
457-
return this._firestoreClient.start(
458-
persistenceSettings,
459-
this._config.settings.cacheSizeBytes
460-
);
436+
return this._firestoreClient.start(persistenceSettings);
461437
}
462438

463439
private static databaseIdFromApp(app: FirebaseApp): DatabaseId {

packages/firestore/src/core/firestore_client.ts

+25-29
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ import {
4545
import { SyncEngine } from './sync_engine';
4646
import { View, ViewDocumentChanges } from './view';
4747

48-
import { PersistenceSettings } from '../api/database';
4948
import {
5049
LruGarbageCollector,
5150
LruParams,
@@ -56,7 +55,6 @@ import {
5655
SharedClientState,
5756
WebStorageSharedClientState
5857
} from '../local/shared_client_state';
59-
import { assert } from '../util/assert';
6058
import { AutoId } from '../util/misc';
6159
import { DatabaseId, DatabaseInfo } from './database_info';
6260
import { Query } from './query';
@@ -72,6 +70,23 @@ const DOM_EXCEPTION_ABORTED = 20;
7270
/** The DOMException code for quota exceeded. */
7371
const DOM_EXCEPTION_QUOTA_EXCEEDED = 22;
7472

73+
export class IndexedDbPersistenceSettings {
74+
constructor(
75+
readonly cacheSizeBytes: number,
76+
readonly experimentalTabSynchronization: boolean
77+
) {}
78+
79+
lruParams(): LruParams {
80+
return LruParams.withCacheSize(this.cacheSizeBytes);
81+
}
82+
}
83+
84+
export class MemoryPersistenceSettings {}
85+
86+
export type InternalPersistenceSettings =
87+
| IndexedDbPersistenceSettings
88+
| MemoryPersistenceSettings;
89+
7590
/**
7691
* FirestoreClient is a top-level class that constructs and owns all of the
7792
* pieces of the client SDK architecture. It is responsible for creating the
@@ -146,10 +161,7 @@ export class FirestoreClient {
146161
* start for any reason. If usePersistence is false this is
147162
* unconditionally resolved.
148163
*/
149-
start(
150-
persistenceSettings: PersistenceSettings,
151-
cacheSizeBytes: number
152-
): Promise<void> {
164+
start(persistenceSettings: InternalPersistenceSettings): Promise<void> {
153165
// We defer our initialization until we get the current user from
154166
// setChangeListener(). We block the async queue until we got the initial
155167
// user and the initialization is completed. This will prevent any scheduled
@@ -172,12 +184,7 @@ export class FirestoreClient {
172184
if (!initialized) {
173185
initialized = true;
174186

175-
this.initializePersistence(
176-
persistenceSettings,
177-
persistenceResult,
178-
user,
179-
cacheSizeBytes
180-
)
187+
this.initializePersistence(persistenceSettings, persistenceResult, user)
181188
.then(maybeLruGc => this.initializeRest(user, maybeLruGc))
182189
.then(initializationDone.resolve, initializationDone.reject);
183190
} else {
@@ -223,17 +230,12 @@ export class FirestoreClient {
223230
* succeeded.
224231
*/
225232
private initializePersistence(
226-
persistenceSettings: PersistenceSettings,
233+
persistenceSettings: InternalPersistenceSettings,
227234
persistenceResult: Deferred<void>,
228-
user: User,
229-
cacheSizeBytes: number
235+
user: User
230236
): Promise<LruGarbageCollector | null> {
231-
if (persistenceSettings.enabled) {
232-
return this.startIndexedDbPersistence(
233-
user,
234-
persistenceSettings,
235-
cacheSizeBytes
236-
)
237+
if (persistenceSettings instanceof IndexedDbPersistenceSettings) {
238+
return this.startIndexedDbPersistence(user, persistenceSettings)
237239
.then(maybeLruGc => {
238240
persistenceResult.resolve();
239241
return maybeLruGc;
@@ -301,14 +303,8 @@ export class FirestoreClient {
301303
*/
302304
private startIndexedDbPersistence(
303305
user: User,
304-
settings: PersistenceSettings,
305-
cacheSizeBytes: number
306+
settings: IndexedDbPersistenceSettings
306307
): Promise<LruGarbageCollector> {
307-
assert(
308-
settings.enabled,
309-
'Should only start IndexedDb persitence with offline persistence enabled.'
310-
);
311-
312308
// TODO(http://b/33384523): For now we just disable garbage collection
313309
// when persistence is enabled.
314310
const storagePrefix = IndexedDbPersistence.buildStoragePrefix(
@@ -331,7 +327,7 @@ export class FirestoreClient {
331327
}
332328

333329
let persistence: IndexedDbPersistence;
334-
const lruParams = LruParams.withCacheSize(cacheSizeBytes);
330+
const lruParams = settings.lruParams();
335331
if (settings.experimentalTabSynchronization) {
336332
this.sharedClientState = new WebStorageSharedClientState(
337333
this.asyncQueue,

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

+4-15
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616

1717
import { expect } from 'chai';
18-
import { PersistenceSettings } from '../../../src/api/database';
1918
import { SnapshotVersion } from '../../../src/core/snapshot_version';
2019
import { decode, encode } from '../../../src/local/encoded_resource_path';
2120
import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence';
@@ -98,7 +97,7 @@ function withDb(
9897

9998
async function withCustomPersistence(
10099
clientId: ClientId,
101-
settings: PersistenceSettings,
100+
multiClient: boolean,
102101
fn: (
103102
persistence: IndexedDbPersistence,
104103
platform: TestPlatform,
@@ -114,7 +113,7 @@ async function withCustomPersistence(
114113
PlatformSupport.getPlatform(),
115114
new SharedFakeWebStorage()
116115
);
117-
const persistence = await (settings.experimentalTabSynchronization
116+
const persistence = await (multiClient
118117
? IndexedDbPersistence.createMultiClientIndexedDbPersistence(
119118
TEST_PERSISTENCE_PREFIX,
120119
clientId,
@@ -147,11 +146,7 @@ async function withPersistence(
147146
queue: AsyncQueue
148147
) => Promise<void>
149148
): Promise<void> {
150-
return withCustomPersistence(
151-
clientId,
152-
new PersistenceSettings(/* enabled */ true),
153-
fn
154-
);
149+
return withCustomPersistence(clientId, /* multiClient= */ false, fn);
155150
}
156151

157152
async function withMultiClientPersistence(
@@ -162,13 +157,7 @@ async function withMultiClientPersistence(
162157
queue: AsyncQueue
163158
) => Promise<void>
164159
): Promise<void> {
165-
return withCustomPersistence(
166-
clientId,
167-
new PersistenceSettings(/* enabled */ true, {
168-
experimentalTabSynchronization: true
169-
}),
170-
fn
171-
);
160+
return withCustomPersistence(clientId, /* multiClient= */ true, fn);
172161
}
173162

174163
function getAllObjectStores(db: IDBDatabase): string[] {

0 commit comments

Comments
 (0)