Skip to content

Commit cad6dc5

Browse files
LocalStore-only queries
1 parent a1ae872 commit cad6dc5

File tree

5 files changed

+299
-322
lines changed

5 files changed

+299
-322
lines changed

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

Lines changed: 110 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,20 @@ import {
2828
OnlineComponentProvider
2929
} from '../../../src/core/component_provider';
3030
import { DEFAULT_HOST, DEFAULT_SSL } from '../../../lite/src/api/components';
31+
import { LocalStore } from '../../../src/local/local_store';
32+
import { Deferred } from '../../../src/util/promise';
3133

3234
// The components module manages the lifetime of dependencies of the Firestore
3335
// client. Dependencies can be lazily constructed and only one exists per
3436
// Firestore instance.
3537

38+
// TODO: These should be promises too
39+
const offlineComponentProviders = new Map<
40+
Firestore,
41+
OfflineComponentProvider
42+
>();
43+
const onlineComponentProviders = new Map<Firestore, OnlineComponentProvider>();
44+
3645
/**
3746
* An instance map that ensures only one FirestoreClient exists per Firestore
3847
* instance.
@@ -56,18 +65,58 @@ export function getFirestoreClient(
5665
}
5766
if (!firestoreClientInstances.has(firestore)) {
5867
// eslint-disable-next-line @typescript-eslint/no-floating-promises
59-
initializeFirestoreClient(
60-
firestore,
61-
new MemoryOfflineComponentProvider(),
62-
new OnlineComponentProvider(),
63-
{
64-
durable: false
65-
}
66-
);
68+
initializeFirestoreClient(firestore, {
69+
durable: false
70+
});
6771
}
6872
return firestoreClientInstances.get(firestore)!;
6973
}
7074

75+
async function getOfflineComponentProvider(
76+
firestore: Firestore
77+
): Promise<OfflineComponentProvider> {
78+
let offlineComponentProvider = offlineComponentProviders.get(firestore);
79+
if (!offlineComponentProvider) {
80+
offlineComponentProvider = new MemoryOfflineComponentProvider();
81+
offlineComponentProviders.set(firestore, offlineComponentProvider);
82+
const componentConfiguration = {
83+
asyncQueue: firestore._queue,
84+
databaseInfo: firestore._databaseId,
85+
clientId: null as any,
86+
credentials: null as any,
87+
initialUser: null as any,
88+
maxConcurrentLimboResolutions: null as any,
89+
persistenceSettings: null as any
90+
};
91+
await offlineComponentProvider.initialize(componentConfiguration as any);
92+
}
93+
return offlineComponentProvider;
94+
}
95+
96+
async function getOnlineComponentProvider(
97+
firestore: Firestore
98+
): Promise<OnlineComponentProvider> {
99+
let onlineComponentProvider = onlineComponentProviders.get(firestore);
100+
if (!onlineComponentProvider) {
101+
onlineComponentProvider = new OnlineComponentProvider();
102+
onlineComponentProviders.set(firestore, onlineComponentProvider);
103+
const componentConfiguration = {
104+
asyncQueue: firestore._queue,
105+
databaseInfo: firestore._databaseId,
106+
clientId: null as any,
107+
credentials: null as any,
108+
initialUser: null as any,
109+
maxConcurrentLimboResolutions: null as any,
110+
persistenceSettings: null as any
111+
};
112+
await onlineComponentProvider.initialize(
113+
await getOfflineComponentProvider(firestore),
114+
componentConfiguration as any
115+
);
116+
}
117+
return onlineComponentProvider;
118+
}
119+
71120
/**
72121
* Creates a new FirestoreClient for the given Firestore instance. Throws if the
73122
* instance exists.
@@ -79,8 +128,6 @@ export function getFirestoreClient(
79128
*/
80129
export function initializeFirestoreClient(
81130
firestore: Firestore,
82-
offlineComponentProvider: OfflineComponentProvider,
83-
onlineComponentProvider: OnlineComponentProvider,
84131
persistenceSettings: PersistenceSettings
85132
): Promise<void> {
86133
if (firestore._initialized) {
@@ -104,17 +151,23 @@ export function initializeFirestoreClient(
104151
firestore._credentials,
105152
firestore._queue
106153
);
107-
const initializationPromise = firestoreClient.start(
108-
databaseInfo,
109-
offlineComponentProvider,
110-
onlineComponentProvider,
111-
persistenceSettings
112-
);
113-
firestoreClientInstances.set(
114-
firestore,
115-
initializationPromise.then(() => firestoreClient)
116-
);
117-
return initializationPromise;
154+
const initializationDeferred = new Deferred<FirestoreClient>();
155+
firestoreClientInstances.set(firestore, initializationDeferred.promise);
156+
157+
Promise.all([
158+
getOfflineComponentProvider(firestore),
159+
getOnlineComponentProvider(firestore)
160+
]).then(([offlineComponentProvider, onlineComponentProvider]) => {
161+
firestoreClient
162+
.start(
163+
databaseInfo,
164+
offlineComponentProvider,
165+
onlineComponentProvider,
166+
persistenceSettings
167+
)
168+
.then(() => initializationDeferred.resolve(firestoreClient));
169+
});
170+
return initializationDeferred.promise.then(() => {});
118171
}
119172

120173
/**
@@ -130,3 +183,39 @@ export async function removeFirestoreClient(
130183
return firestoreClient.terminate();
131184
}
132185
}
186+
187+
export async function setComponentProviders(
188+
firestore: Firestore,
189+
offlineComponentProvider: OfflineComponentProvider,
190+
onlineComponentProvider: OnlineComponentProvider
191+
): Promise<void> {
192+
// TODO: Move this to Firestore
193+
const componentConfiguration = {
194+
asyncQueue: firestore._queue,
195+
databaseInfo: firestore._databaseId,
196+
clientId: null as any,
197+
credentials: null as any,
198+
initialUser: null as any,
199+
maxConcurrentLimboResolutions: null as any,
200+
persistenceSettings: null as any
201+
};
202+
await offlineComponentProvider.initialize(componentConfiguration as any);
203+
await onlineComponentProvider.initialize(
204+
offlineComponentProvider,
205+
componentConfiguration as any
206+
);
207+
offlineComponentProviders.set(firestore, offlineComponentProvider);
208+
onlineComponentProviders.set(firestore, onlineComponentProvider);
209+
}
210+
211+
export function getLocalStore(firestore: Firestore): Promise<LocalStore> {
212+
if (firestore._terminated) {
213+
throw new FirestoreError(
214+
Code.FAILED_PRECONDITION,
215+
'The client has already been terminated.'
216+
);
217+
}
218+
return getOfflineComponentProvider(firestore).then(
219+
provider => provider.localStore
220+
);
221+
}

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

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ import {
3737
import {
3838
getFirestoreClient,
3939
initializeFirestoreClient,
40-
removeFirestoreClient
40+
removeFirestoreClient,
41+
setComponentProviders
4142
} from './components';
4243
import {
4344
IndexedDbOfflineComponentProvider,
@@ -113,17 +114,18 @@ export function enableIndexedDbPersistence(
113114
): Promise<void> {
114115
const firestoreImpl = cast(firestore, Firestore);
115116
const settings = firestoreImpl._getSettings();
116-
return initializeFirestoreClient(
117+
return setComponentProviders(
117118
firestoreImpl,
118119
new IndexedDbOfflineComponentProvider(),
119-
new OnlineComponentProvider(),
120-
{
120+
new OnlineComponentProvider()
121+
).then(() =>
122+
initializeFirestoreClient(firestoreImpl, {
121123
durable: true,
122124
synchronizeTabs: false,
123125
cacheSizeBytes:
124126
settings.cacheSizeBytes || LruParams.DEFAULT_CACHE_SIZE_BYTES,
125127
forceOwningTab: false
126-
}
128+
})
127129
);
128130
}
129131

@@ -132,17 +134,18 @@ export function enableMultiTabIndexedDbPersistence(
132134
): Promise<void> {
133135
const firestoreImpl = cast(firestore, Firestore);
134136
const settings = firestoreImpl._getSettings();
135-
return initializeFirestoreClient(
137+
return setComponentProviders(
136138
firestoreImpl,
137139
new MultiTabOfflineComponentProvider(),
138-
new MultiTabOnlineComponentProvider(),
139-
{
140+
new MultiTabOnlineComponentProvider()
141+
).then(() =>
142+
initializeFirestoreClient(firestoreImpl, {
140143
durable: true,
141144
synchronizeTabs: true,
142145
cacheSizeBytes:
143146
settings.cacheSizeBytes || LruParams.DEFAULT_CACHE_SIZE_BYTES,
144147
forceOwningTab: false
145-
}
148+
})
146149
);
147150
}
148151

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ import {
5959
PartialObserver,
6060
Unsubscribe
6161
} from '../../../src/api/observer';
62-
import { getFirestoreClient } from './components';
62+
import { getFirestoreClient, getLocalStore } from './components';
63+
import {
64+
getDocumentFromLocalCache,
65+
getDocumentsFromLocalCache
66+
} from '../../../src/core/firestore_client';
6367

6468
export function getDoc<T>(
6569
reference: firestore.DocumentReference<T>
@@ -75,15 +79,17 @@ export function getDoc<T>(
7579
});
7680
}
7781

78-
// TODO(firestorexp): Make sure we don't include Datastore/RemoteStore in builds
79-
// that only include `getDocFromCache`.
8082
export function getDocFromCache<T>(
8183
reference: firestore.DocumentReference<T>
8284
): Promise<firestore.DocumentSnapshot<T>> {
8385
const ref = cast<DocumentReference<T>>(reference, DocumentReference);
8486
const firestore = cast<Firestore>(ref.firestore, Firestore);
85-
return getFirestoreClient(firestore).then(async firestoreClient => {
86-
const doc = await firestoreClient.getDocumentFromLocalCache(ref._key);
87+
return getLocalStore(firestore).then(async localStore => {
88+
const doc = await getDocumentFromLocalCache(
89+
firestore._queue,
90+
localStore,
91+
ref._key
92+
);
8793
return new DocumentSnapshot(
8894
firestore,
8995
ref._key,
@@ -133,8 +139,10 @@ export function getQueryFromCache<T>(
133139
): Promise<QuerySnapshot<T>> {
134140
const internalQuery = cast<Query<T>>(query, Query);
135141
const firestore = cast<Firestore>(query.firestore, Firestore);
136-
return getFirestoreClient(firestore).then(async firestoreClient => {
137-
const snapshot = await firestoreClient.getDocumentsFromLocalCache(
142+
return getLocalStore(firestore).then(async localStore => {
143+
const snapshot = await getDocumentsFromLocalCache(
144+
firestore._queue,
145+
localStore,
138146
internalQuery._query
139147
);
140148
return new QuerySnapshot(firestore, internalQuery, snapshot);

0 commit comments

Comments
 (0)