Skip to content

Commit 86ee9fa

Browse files
MockIndexedDbPersistence
1 parent dc09fd1 commit 86ee9fa

7 files changed

+88
-135
lines changed

packages/firestore/src/core/component_provider.ts

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ export class MemoryComponentProvider implements ComponentProvider {
180180
* Provides all components needed for Firestore with IndexedDB persistence.
181181
*/
182182
export class IndexedDbComponentProvider extends MemoryComponentProvider {
183+
persistence!: IndexedDbPersistence;
184+
183185
// TODO(tree-shaking): Create an IndexedDbComponentProvider and a
184186
// MultiTabComponentProvider. The IndexedDbComponentProvider should depend
185187
// on LocalStore and SyncEngine.
@@ -189,11 +191,6 @@ export class IndexedDbComponentProvider extends MemoryComponentProvider {
189191
async initialize(cfg: ComponentConfiguration): Promise<void> {
190192
await super.initialize(cfg);
191193

192-
debugAssert(
193-
this.persistence instanceof IndexedDbPersistence,
194-
'IndexedDbComponentProvider should provide IndexedDBPersistence'
195-
);
196-
197194
// NOTE: This will immediately call the listener, so we make sure to
198195
// set it after localStore / remoteStore are started.
199196
await this.persistence.setPrimaryStateListener(async isPrimary => {
@@ -211,10 +208,6 @@ export class IndexedDbComponentProvider extends MemoryComponentProvider {
211208
}
212209

213210
createLocalStore(cfg: ComponentConfiguration): LocalStore {
214-
debugAssert(
215-
this.persistence instanceof IndexedDbPersistence,
216-
'IndexedDbComponentProvider should provide IndexedDBPersistence'
217-
);
218211
return new MultiTabLocalStore(
219212
this.persistence,
220213
new IndexFreeQueryEngine(),
@@ -239,10 +232,6 @@ export class IndexedDbComponentProvider extends MemoryComponentProvider {
239232
createGarbageCollectionScheduler(
240233
cfg: ComponentConfiguration
241234
): GarbageCollectionScheduler | null {
242-
debugAssert(
243-
this.persistence instanceof IndexedDbPersistence,
244-
'IndexedDbComponentProvider should provide IndexedDBPersistence'
245-
);
246235
const garbageCollector = this.persistence.referenceDelegate
247236
.garbageCollector;
248237
return new LruScheduler(garbageCollector, cfg.asyncQueue);
@@ -258,18 +247,16 @@ export class IndexedDbComponentProvider extends MemoryComponentProvider {
258247
cfg.databaseInfo
259248
);
260249
const serializer = cfg.platform.newSerializer(cfg.databaseInfo.databaseId);
261-
return IndexedDbPersistence.createIndexedDbPersistence({
262-
allowTabSynchronization: cfg.persistenceSettings.synchronizeTabs,
250+
return new IndexedDbPersistence(
251+
cfg.persistenceSettings.synchronizeTabs,
263252
persistenceKey,
264-
clientId: cfg.clientId,
265-
platform: cfg.platform,
266-
queue: cfg.asyncQueue,
253+
cfg.clientId,
254+
cfg.platform,
255+
LruParams.withCacheSize(cfg.persistenceSettings.cacheSizeBytes),
256+
cfg.asyncQueue,
267257
serializer,
268-
lruParams: LruParams.withCacheSize(
269-
cfg.persistenceSettings.cacheSizeBytes
270-
),
271-
sequenceNumberSyncer: this.sharedClientState
272-
});
258+
this.sharedClientState
259+
);
273260
}
274261

275262
createSharedClientState(cfg: ComponentConfiguration): SharedClientState {

packages/firestore/src/local/indexeddb_persistence.ts

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -188,36 +188,6 @@ export class IndexedDbPersistence implements Persistence {
188188
*/
189189
static MAIN_DATABASE = 'main';
190190

191-
static createIndexedDbPersistence(options: {
192-
allowTabSynchronization: boolean;
193-
persistenceKey: string;
194-
clientId: ClientId;
195-
platform: Platform;
196-
lruParams: LruParams;
197-
queue: AsyncQueue;
198-
serializer: JsonProtoSerializer;
199-
sequenceNumberSyncer: SequenceNumberSyncer;
200-
}): IndexedDbPersistence {
201-
if (!IndexedDbPersistence.isAvailable()) {
202-
throw new FirestoreError(
203-
Code.UNIMPLEMENTED,
204-
UNSUPPORTED_PLATFORM_ERROR_MSG
205-
);
206-
}
207-
208-
const persistence = new IndexedDbPersistence(
209-
options.allowTabSynchronization,
210-
options.persistenceKey,
211-
options.clientId,
212-
options.platform,
213-
options.lruParams,
214-
options.queue,
215-
options.serializer,
216-
options.sequenceNumberSyncer
217-
);
218-
return persistence;
219-
}
220-
221191
private readonly document: Document | null;
222192
private readonly window: Window;
223193

@@ -256,7 +226,7 @@ export class IndexedDbPersistence implements Persistence {
256226
private readonly webStorage: Storage;
257227
readonly referenceDelegate: IndexedDbLruDelegate;
258228

259-
private constructor(
229+
constructor(
260230
private readonly allowTabSynchronization: boolean,
261231
private readonly persistenceKey: string,
262232
private readonly clientId: ClientId,
@@ -266,6 +236,13 @@ export class IndexedDbPersistence implements Persistence {
266236
serializer: JsonProtoSerializer,
267237
private readonly sequenceNumberSyncer: SequenceNumberSyncer
268238
) {
239+
if (!IndexedDbPersistence.isAvailable()) {
240+
throw new FirestoreError(
241+
Code.UNIMPLEMENTED,
242+
UNSUPPORTED_PLATFORM_ERROR_MSG
243+
);
244+
}
245+
269246
this.referenceDelegate = new IndexedDbLruDelegate(this, lruParams);
270247
this.dbName = persistenceKey + IndexedDbPersistence.MAIN_DATABASE;
271248
this.serializer = new LocalSerializer(serializer);

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,16 +124,16 @@ async function withCustomPersistence(
124124
PlatformSupport.getPlatform(),
125125
new SharedFakeWebStorage()
126126
);
127-
const persistence = await IndexedDbPersistence.createIndexedDbPersistence({
128-
allowTabSynchronization: multiClient,
129-
persistenceKey: TEST_PERSISTENCE_PREFIX,
127+
const persistence = new IndexedDbPersistence(
128+
/* allowTabSynchronization= */ multiClient,
129+
TEST_PERSISTENCE_PREFIX,
130130
clientId,
131131
platform,
132+
LruParams.DEFAULT,
132133
queue,
133134
serializer,
134-
lruParams: LruParams.DEFAULT,
135-
sequenceNumberSyncer: MOCK_SEQUENCE_NUMBER_SYNCER
136-
});
135+
MOCK_SEQUENCE_NUMBER_SYNCER
136+
);
137137

138138
await persistence.start();
139139
await fn(persistence, platform, queue);

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,16 @@ export async function testIndexedDbPersistence(
113113
await SimpleDb.delete(prefix + IndexedDbPersistence.MAIN_DATABASE);
114114
}
115115
const platform = PlatformSupport.getPlatform();
116-
const persistence = IndexedDbPersistence.createIndexedDbPersistence({
117-
allowTabSynchronization: !!options.synchronizeTabs,
118-
persistenceKey: TEST_PERSISTENCE_PREFIX,
116+
const persistence = new IndexedDbPersistence(
117+
!!options.synchronizeTabs,
118+
TEST_PERSISTENCE_PREFIX,
119119
clientId,
120120
platform,
121-
queue,
122-
serializer: JSON_SERIALIZER,
123121
lruParams,
124-
sequenceNumberSyncer: MOCK_SEQUENCE_NUMBER_SYNCER
125-
});
122+
queue,
123+
JSON_SERIALIZER,
124+
MOCK_SEQUENCE_NUMBER_SYNCER
125+
);
126126
await persistence.start();
127127
return persistence;
128128
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export class TestRemoteDocumentCache {
134134
txn => {
135135
debugAssert(
136136
this.cache instanceof IndexedDbRemoteDocumentCache,
137-
'getNewDocumentChanges is only supported by IndexedDB'
137+
'getNewDocumentChanges() requires IndexedDB'
138138
);
139139
return this.cache.getNewDocumentChanges(txn, sinceReadTime);
140140
}

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

Lines changed: 48 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,8 @@ import {
2424
GarbageCollectionScheduler,
2525
Persistence,
2626
PersistenceTransaction,
27-
PersistenceTransactionMode,
28-
PrimaryStateListener,
29-
ReferenceDelegate
27+
PersistenceTransactionMode
3028
} from '../../../src/local/persistence';
31-
import { ClientId } from '../../../src/local/shared_client_state';
32-
import { User } from '../../../src/auth/user';
33-
import { MutationQueue } from '../../../src/local/mutation_queue';
34-
import { TargetCache } from '../../../src/local/target_cache';
35-
import { RemoteDocumentCache } from '../../../src/local/remote_document_cache';
36-
import { IndexManager } from '../../../src/local/index_manager';
3729
import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence';
3830
import { PersistencePromise } from '../../../src/local/persistence_promise';
3931
import { debugAssert } from '../../../src/util/assert';
@@ -45,60 +37,33 @@ import {
4537
import { LruParams } from '../../../src/local/lru_garbage_collector';
4638

4739
/**
48-
* A test-only persistence implementation that delegates all calls to the
49-
* underlying IndexedDB or Memory-based persistence implementations and is able
50-
* to inject transaction failures.
40+
* A test-only MemoryPersistence implementation that is able to inject
41+
* transaction failures.
5142
*/
52-
export class MockPersistence implements Persistence {
43+
export class MockMemoryPersistence extends MemoryPersistence {
5344
injectFailures = false;
5445

55-
constructor(private readonly delegate: Persistence) {}
56-
57-
start(): Promise<void> {
58-
return this.delegate.start();
59-
}
60-
61-
get started(): boolean {
62-
return this.delegate.started;
63-
}
64-
65-
get referenceDelegate(): ReferenceDelegate {
66-
return this.delegate.referenceDelegate;
67-
}
68-
69-
shutdown(): Promise<void> {
70-
return this.delegate.shutdown();
71-
}
72-
73-
setDatabaseDeletedListener(
74-
databaseDeletedListener: () => Promise<void>
75-
): void {
76-
this.delegate.setDatabaseDeletedListener(databaseDeletedListener);
77-
}
78-
79-
getActiveClients(): Promise<ClientId[]> {
80-
debugAssert(
81-
this.delegate instanceof IndexedDbPersistence,
82-
`getActiveClients() requires IndexedDbPersistence`
83-
);
84-
return this.delegate.getActiveClients();
85-
}
86-
87-
getMutationQueue(user: User): MutationQueue {
88-
return this.delegate.getMutationQueue(user);
89-
}
90-
91-
getTargetCache(): TargetCache {
92-
return this.delegate.getTargetCache();
93-
}
94-
95-
getRemoteDocumentCache(): RemoteDocumentCache {
96-
return this.delegate.getRemoteDocumentCache();
46+
runTransaction<T>(
47+
action: string,
48+
mode: PersistenceTransactionMode,
49+
transactionOperation: (
50+
transaction: PersistenceTransaction
51+
) => PersistencePromise<T>
52+
): Promise<T> {
53+
if (this.injectFailures) {
54+
return Promise.reject(new Error('Injected Failure'));
55+
} else {
56+
return super.runTransaction(action, mode, transactionOperation);
57+
}
9758
}
59+
}
9860

99-
getIndexManager(): IndexManager {
100-
return this.delegate.getIndexManager();
101-
}
61+
/**
62+
* A test-only IndexedDbPersistence implementation that is able to inject
63+
* transaction failures.
64+
*/
65+
export class MockIndexedDbPersistence extends IndexedDbPersistence {
66+
injectFailures = false;
10267

10368
runTransaction<T>(
10469
action: string,
@@ -110,27 +75,46 @@ export class MockPersistence implements Persistence {
11075
if (this.injectFailures) {
11176
return Promise.reject(new Error('Injected Failure'));
11277
} else {
113-
return this.delegate.runTransaction(action, mode, transactionOperation);
78+
return super.runTransaction(action, mode, transactionOperation);
11479
}
11580
}
11681
}
11782

11883
export class MockIndexedDbComponentProvider extends IndexedDbComponentProvider {
119-
persistence!: MockPersistence;
84+
persistence!: MockIndexedDbPersistence;
12085

12186
createGarbageCollectionScheduler(
12287
cfg: ComponentConfiguration
12388
): GarbageCollectionScheduler | null {
12489
return null;
12590
}
12691

127-
createPersistence(cfg: ComponentConfiguration): Persistence {
128-
return new MockPersistence(super.createPersistence(cfg));
92+
createPersistence(cfg: ComponentConfiguration): MockIndexedDbPersistence {
93+
debugAssert(
94+
cfg.persistenceSettings.durable,
95+
'Can only start durable persistence'
96+
);
97+
98+
const persistenceKey = IndexedDbPersistence.buildStoragePrefix(
99+
cfg.databaseInfo
100+
);
101+
const serializer = cfg.platform.newSerializer(cfg.databaseInfo.databaseId);
102+
103+
return new MockIndexedDbPersistence(
104+
/* allowTabSynchronization= */ true,
105+
persistenceKey,
106+
cfg.clientId,
107+
cfg.platform,
108+
LruParams.withCacheSize(cfg.persistenceSettings.cacheSizeBytes),
109+
cfg.asyncQueue,
110+
serializer,
111+
this.sharedClientState
112+
);
129113
}
130114
}
131115

132116
export class MockMemoryComponentProvider extends MemoryComponentProvider {
133-
persistence!: MockPersistence;
117+
persistence!: MockMemoryPersistence;
134118

135119
constructor(private readonly gcEnabled: boolean) {
136120
super();
@@ -147,11 +131,10 @@ export class MockMemoryComponentProvider extends MemoryComponentProvider {
147131
!cfg.persistenceSettings.durable,
148132
'Can only start memory persistence'
149133
);
150-
const persistence = new MemoryPersistence(
134+
return new MockMemoryPersistence(
151135
this.gcEnabled
152136
? MemoryEagerDelegate.factory
153137
: p => new MemoryLruDelegate(p, LruParams.DEFAULT)
154138
);
155-
return new MockPersistence(persistence);
156139
}
157140
}

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,11 @@ import { LruParams } from '../../../src/local/lru_garbage_collector';
108108
import { PersistenceSettings } from '../../../src/core/firestore_client';
109109
import {
110110
MockIndexedDbComponentProvider,
111+
MockIndexedDbPersistence,
111112
MockMemoryComponentProvider,
112-
MockPersistence
113+
MockMemoryPersistence
113114
} from './spec_test_components';
115+
import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence';
114116

115117
const ARBITRARY_SEQUENCE_NUMBER = 2;
116118

@@ -415,7 +417,7 @@ abstract class TestRunner {
415417
private datastore!: Datastore;
416418
private localStore!: LocalStore;
417419
private remoteStore!: RemoteStore;
418-
private persistence!: MockPersistence;
420+
private persistence!: MockMemoryPersistence | MockIndexedDbPersistence;
419421
protected sharedClientState!: SharedClientState;
420422

421423
private useGarbageCollection: boolean;
@@ -1004,6 +1006,10 @@ abstract class TestRunner {
10041006
);
10051007
}
10061008
if ('numActiveClients' in expectedState) {
1009+
debugAssert(
1010+
this.persistence instanceof IndexedDbPersistence,
1011+
'numActiveClients() requires IndexedDbPersistence'
1012+
);
10071013
const activeClients = await this.persistence.getActiveClients();
10081014
expect(activeClients.length).to.equal(expectedState.numActiveClients);
10091015
}

0 commit comments

Comments
 (0)