@firebase/firestore 3.4.6 → 3.4.7-2022222232915
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/firestore/src/core/bundle.d.ts +2 -2
- package/dist/firestore/src/core/bundle_impl.d.ts +2 -0
- package/dist/firestore/src/core/query.d.ts +7 -0
- package/dist/firestore/src/core/snapshot_version.d.ts +1 -0
- package/dist/firestore/src/core/sync_engine_impl.d.ts +1 -1
- package/dist/firestore/src/local/indexeddb_mutation_batch_impl.d.ts +2 -1
- package/dist/firestore/src/local/indexeddb_remote_document_cache.d.ts +0 -17
- package/dist/firestore/src/local/indexeddb_schema.d.ts +16 -13
- package/dist/firestore/src/local/indexeddb_schema_converter.d.ts +1 -0
- package/dist/firestore/src/local/indexeddb_schema_legacy.d.ts +29 -0
- package/dist/firestore/src/local/indexeddb_sentinels.d.ts +22 -17
- package/dist/firestore/src/local/local_documents_view.d.ts +3 -4
- package/dist/firestore/src/local/local_serializer.d.ts +2 -1
- package/dist/firestore/src/local/local_store_impl.d.ts +1 -7
- package/dist/firestore/src/local/remote_document_cache.d.ts +13 -4
- package/dist/firestore/src/local/shared_client_state.d.ts +6 -3
- package/dist/firestore/src/local/shared_client_state_schema.d.ts +1 -1
- package/dist/firestore/src/local/shared_client_state_syncer.d.ts +1 -1
- package/dist/firestore/src/model/field_index.d.ts +8 -1
- package/dist/firestore/test/unit/local/test_remote_document_cache.d.ts +3 -1
- package/dist/index.esm2017.js +3206 -3134
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm5.js +3579 -3453
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +403 -244
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/index.node.mjs +403 -244
- package/dist/index.node.mjs.map +1 -1
- package/dist/index.rn.js +3160 -3088
- package/dist/index.rn.js.map +1 -1
- package/dist/internal.d.ts +19 -5
- package/dist/lite/firestore/src/core/bundle.d.ts +2 -2
- package/dist/lite/firestore/src/core/bundle_impl.d.ts +2 -0
- package/dist/lite/firestore/src/core/query.d.ts +7 -0
- package/dist/lite/firestore/src/core/snapshot_version.d.ts +1 -0
- package/dist/lite/firestore/src/core/sync_engine_impl.d.ts +1 -1
- package/dist/lite/firestore/src/local/indexeddb_mutation_batch_impl.d.ts +2 -1
- package/dist/lite/firestore/src/local/indexeddb_remote_document_cache.d.ts +0 -17
- package/dist/lite/firestore/src/local/indexeddb_schema.d.ts +16 -13
- package/dist/lite/firestore/src/local/indexeddb_schema_converter.d.ts +1 -0
- package/dist/lite/firestore/src/local/indexeddb_schema_legacy.d.ts +29 -0
- package/dist/lite/firestore/src/local/indexeddb_sentinels.d.ts +22 -17
- package/dist/lite/firestore/src/local/local_documents_view.d.ts +3 -4
- package/dist/lite/firestore/src/local/local_serializer.d.ts +2 -1
- package/dist/lite/firestore/src/local/local_store_impl.d.ts +1 -7
- package/dist/lite/firestore/src/local/remote_document_cache.d.ts +13 -4
- package/dist/lite/firestore/src/local/shared_client_state.d.ts +6 -3
- package/dist/lite/firestore/src/local/shared_client_state_schema.d.ts +1 -1
- package/dist/lite/firestore/src/local/shared_client_state_syncer.d.ts +1 -1
- package/dist/lite/firestore/src/model/field_index.d.ts +8 -1
- package/dist/lite/firestore/test/unit/local/test_remote_document_cache.d.ts +3 -1
- package/dist/lite/index.browser.esm2017.js +5 -2
- package/dist/lite/index.browser.esm2017.js.map +1 -1
- package/dist/lite/index.browser.esm5.js +94 -92
- package/dist/lite/index.browser.esm5.js.map +1 -1
- package/dist/lite/index.node.cjs.js +5 -2
- package/dist/lite/index.node.cjs.js.map +1 -1
- package/dist/lite/index.node.mjs +5 -2
- package/dist/lite/index.node.mjs.map +1 -1
- package/dist/lite/index.rn.esm2017.js +5 -2
- package/dist/lite/index.rn.esm2017.js.map +1 -1
- package/dist/lite/internal.d.ts +1 -0
- package/dist/lite/packages/firestore/src/core/bundle.d.ts +2 -2
- package/dist/lite/packages/firestore/src/core/bundle_impl.d.ts +2 -0
- package/dist/lite/packages/firestore/src/core/query.d.ts +7 -0
- package/dist/lite/packages/firestore/src/core/snapshot_version.d.ts +1 -0
- package/dist/lite/packages/firestore/src/core/sync_engine_impl.d.ts +1 -1
- package/dist/lite/packages/firestore/src/local/indexeddb_mutation_batch_impl.d.ts +2 -1
- package/dist/lite/packages/firestore/src/local/indexeddb_remote_document_cache.d.ts +0 -17
- package/dist/lite/packages/firestore/src/local/indexeddb_schema.d.ts +16 -13
- package/dist/lite/packages/firestore/src/local/indexeddb_schema_converter.d.ts +1 -0
- package/dist/lite/packages/firestore/src/local/indexeddb_schema_legacy.d.ts +29 -0
- package/dist/lite/packages/firestore/src/local/indexeddb_sentinels.d.ts +22 -17
- package/dist/lite/packages/firestore/src/local/local_documents_view.d.ts +3 -4
- package/dist/lite/packages/firestore/src/local/local_serializer.d.ts +2 -1
- package/dist/lite/packages/firestore/src/local/local_store_impl.d.ts +1 -7
- package/dist/lite/packages/firestore/src/local/remote_document_cache.d.ts +13 -4
- package/dist/lite/packages/firestore/src/local/shared_client_state.d.ts +6 -3
- package/dist/lite/packages/firestore/src/local/shared_client_state_schema.d.ts +1 -1
- package/dist/lite/packages/firestore/src/local/shared_client_state_syncer.d.ts +1 -1
- package/dist/lite/packages/firestore/src/model/field_index.d.ts +8 -1
- package/dist/lite/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +3 -1
- package/dist/lite/private.d.ts +1 -0
- package/dist/packages/firestore/dist/index.esm2017.d.ts +178 -178
- package/dist/packages/firestore/src/core/bundle.d.ts +2 -2
- package/dist/packages/firestore/src/core/bundle_impl.d.ts +2 -0
- package/dist/packages/firestore/src/core/query.d.ts +7 -0
- package/dist/packages/firestore/src/core/snapshot_version.d.ts +1 -0
- package/dist/packages/firestore/src/core/sync_engine_impl.d.ts +1 -1
- package/dist/packages/firestore/src/local/indexeddb_mutation_batch_impl.d.ts +2 -1
- package/dist/packages/firestore/src/local/indexeddb_remote_document_cache.d.ts +0 -17
- package/dist/packages/firestore/src/local/indexeddb_schema.d.ts +16 -13
- package/dist/packages/firestore/src/local/indexeddb_schema_converter.d.ts +1 -0
- package/dist/packages/firestore/src/local/indexeddb_schema_legacy.d.ts +29 -0
- package/dist/packages/firestore/src/local/indexeddb_sentinels.d.ts +22 -17
- package/dist/packages/firestore/src/local/local_documents_view.d.ts +3 -4
- package/dist/packages/firestore/src/local/local_serializer.d.ts +2 -1
- package/dist/packages/firestore/src/local/local_store_impl.d.ts +1 -7
- package/dist/packages/firestore/src/local/remote_document_cache.d.ts +13 -4
- package/dist/packages/firestore/src/local/shared_client_state.d.ts +6 -3
- package/dist/packages/firestore/src/local/shared_client_state_schema.d.ts +1 -1
- package/dist/packages/firestore/src/local/shared_client_state_syncer.d.ts +1 -1
- package/dist/packages/firestore/src/model/field_index.d.ts +8 -1
- package/dist/packages/firestore/test/unit/local/test_remote_document_cache.d.ts +3 -1
- package/dist/private.d.ts +19 -5
- package/package.json +7 -7
package/dist/index.node.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import * as grpc from '@grpc/grpc-js';
|
|
|
8
8
|
import * as protoLoader from '@grpc/proto-loader';
|
|
9
9
|
|
|
10
10
|
const name = "@firebase/firestore";
|
|
11
|
-
const version$1 = "3.4.
|
|
11
|
+
const version$1 = "3.4.7-2022222232915";
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* @license
|
|
@@ -61,7 +61,7 @@ User.GOOGLE_CREDENTIALS = new User('google-credentials-uid');
|
|
|
61
61
|
User.FIRST_PARTY = new User('first-party-uid');
|
|
62
62
|
User.MOCK_USER = new User('mock-user');
|
|
63
63
|
|
|
64
|
-
const version = "9.6.
|
|
64
|
+
const version = "9.6.10-2022222232915";
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
* @license
|
|
@@ -1200,6 +1200,24 @@ function decodeResourcePath(path) {
|
|
|
1200
1200
|
return new ResourcePath(segments);
|
|
1201
1201
|
}
|
|
1202
1202
|
|
|
1203
|
+
/**
|
|
1204
|
+
* @license
|
|
1205
|
+
* Copyright 2022 Google LLC
|
|
1206
|
+
*
|
|
1207
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
1208
|
+
* you may not use this file except in compliance with the License.
|
|
1209
|
+
* You may obtain a copy of the License at
|
|
1210
|
+
*
|
|
1211
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
1212
|
+
*
|
|
1213
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
1214
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
1215
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1216
|
+
* See the License for the specific language governing permissions and
|
|
1217
|
+
* limitations under the License.
|
|
1218
|
+
*/
|
|
1219
|
+
const DbRemoteDocumentStore$1 = 'remoteDocuments';
|
|
1220
|
+
|
|
1203
1221
|
/**
|
|
1204
1222
|
* @license
|
|
1205
1223
|
* Copyright 2022 Google LLC
|
|
@@ -1270,26 +1288,36 @@ function newDbDocumentMutationKey(userId, path, batchId) {
|
|
|
1270
1288
|
*/
|
|
1271
1289
|
const DbDocumentMutationPlaceholder = {};
|
|
1272
1290
|
const DbDocumentMutationStore = 'documentMutations';
|
|
1273
|
-
const DbRemoteDocumentStore = '
|
|
1291
|
+
const DbRemoteDocumentStore = 'remoteDocumentsV14';
|
|
1274
1292
|
/**
|
|
1275
|
-
*
|
|
1276
|
-
*
|
|
1277
|
-
*
|
|
1278
|
-
* This index is used to provide a changelog for Multi-Tab.
|
|
1293
|
+
* The primary key of the remote documents store, which allows for efficient
|
|
1294
|
+
* access by collection path and read time.
|
|
1279
1295
|
*/
|
|
1280
|
-
const
|
|
1281
|
-
|
|
1296
|
+
const DbRemoteDocumentKeyPath = [
|
|
1297
|
+
'prefixPath',
|
|
1298
|
+
'collectionGroup',
|
|
1299
|
+
'readTime',
|
|
1300
|
+
'documentId'
|
|
1301
|
+
];
|
|
1302
|
+
/** An index that provides access to documents by key. */
|
|
1303
|
+
const DbRemoteDocumentDocumentKeyIndex = 'documentKeyIndex';
|
|
1304
|
+
const DbRemoteDocumentDocumentKeyIndexPath = [
|
|
1305
|
+
'prefixPath',
|
|
1306
|
+
'collectionGroup',
|
|
1307
|
+
'documentId'
|
|
1308
|
+
];
|
|
1282
1309
|
/**
|
|
1283
|
-
* An index that provides access to documents
|
|
1310
|
+
* An index that provides access to documents by collection group and read
|
|
1284
1311
|
* time.
|
|
1285
1312
|
*
|
|
1286
|
-
* This index is used
|
|
1287
|
-
* documents in a collection.
|
|
1313
|
+
* This index is used by the index backfiller.
|
|
1288
1314
|
*/
|
|
1289
|
-
const
|
|
1290
|
-
const
|
|
1291
|
-
'
|
|
1292
|
-
'readTime'
|
|
1315
|
+
const DbRemoteDocumentCollectionGroupIndex = 'collectionGroupIndex';
|
|
1316
|
+
const DbRemoteDocumentCollectionGroupIndexPath = [
|
|
1317
|
+
'collectionGroup',
|
|
1318
|
+
'readTime',
|
|
1319
|
+
'prefixPath',
|
|
1320
|
+
'documentId'
|
|
1293
1321
|
];
|
|
1294
1322
|
const DbRemoteDocumentGlobalStore = 'remoteDocumentGlobal';
|
|
1295
1323
|
const DbRemoteDocumentGlobalKey = 'remoteDocumentGlobalKey';
|
|
@@ -1397,7 +1425,7 @@ const V1_STORES = [
|
|
|
1397
1425
|
DbMutationQueueStore,
|
|
1398
1426
|
DbMutationBatchStore,
|
|
1399
1427
|
DbDocumentMutationStore,
|
|
1400
|
-
DbRemoteDocumentStore,
|
|
1428
|
+
DbRemoteDocumentStore$1,
|
|
1401
1429
|
DbTargetStore,
|
|
1402
1430
|
DbPrimaryClientStore,
|
|
1403
1431
|
DbTargetGlobalStore,
|
|
@@ -1412,14 +1440,33 @@ const V8_STORES = [...V6_STORES, DbCollectionParentStore];
|
|
|
1412
1440
|
const V11_STORES = [...V8_STORES, DbBundleStore, DbNamedQueryStore];
|
|
1413
1441
|
const V12_STORES = [...V11_STORES, DbDocumentOverlayStore];
|
|
1414
1442
|
const V13_STORES = [
|
|
1415
|
-
|
|
1443
|
+
DbMutationQueueStore,
|
|
1444
|
+
DbMutationBatchStore,
|
|
1445
|
+
DbDocumentMutationStore,
|
|
1446
|
+
DbRemoteDocumentStore,
|
|
1447
|
+
DbTargetStore,
|
|
1448
|
+
DbPrimaryClientStore,
|
|
1449
|
+
DbTargetGlobalStore,
|
|
1450
|
+
DbTargetDocumentStore,
|
|
1451
|
+
DbClientMetadataStore,
|
|
1452
|
+
DbRemoteDocumentGlobalStore,
|
|
1453
|
+
DbCollectionParentStore,
|
|
1454
|
+
DbBundleStore,
|
|
1455
|
+
DbNamedQueryStore,
|
|
1456
|
+
DbDocumentOverlayStore
|
|
1457
|
+
];
|
|
1458
|
+
const V14_STORES = [
|
|
1459
|
+
...V13_STORES,
|
|
1416
1460
|
DbIndexConfigurationStore,
|
|
1417
1461
|
DbIndexStateStore,
|
|
1418
1462
|
DbIndexEntryStore
|
|
1419
1463
|
];
|
|
1420
1464
|
/** Returns the object stores for the provided schema. */
|
|
1421
1465
|
function getObjectStores(schemaVersion) {
|
|
1422
|
-
if (schemaVersion ===
|
|
1466
|
+
if (schemaVersion === 14) {
|
|
1467
|
+
return V14_STORES;
|
|
1468
|
+
}
|
|
1469
|
+
else if (schemaVersion === 13) {
|
|
1423
1470
|
return V13_STORES;
|
|
1424
1471
|
}
|
|
1425
1472
|
else if (schemaVersion === 12) {
|
|
@@ -2630,6 +2677,9 @@ class SnapshotVersion {
|
|
|
2630
2677
|
static min() {
|
|
2631
2678
|
return new SnapshotVersion(new Timestamp(0, 0));
|
|
2632
2679
|
}
|
|
2680
|
+
static max() {
|
|
2681
|
+
return new SnapshotVersion(new Timestamp(253402300799, 1e9 - 1));
|
|
2682
|
+
}
|
|
2633
2683
|
compareTo(other) {
|
|
2634
2684
|
return this.timestamp._compareTo(other.timestamp);
|
|
2635
2685
|
}
|
|
@@ -4181,6 +4231,28 @@ class IndexState {
|
|
|
4181
4231
|
return new IndexState(INITIAL_SEQUENCE_NUMBER, IndexOffset.min());
|
|
4182
4232
|
}
|
|
4183
4233
|
}
|
|
4234
|
+
/**
|
|
4235
|
+
* Creates an offset that matches all documents with a read time higher than
|
|
4236
|
+
* `readTime`.
|
|
4237
|
+
*/
|
|
4238
|
+
function newIndexOffsetSuccessorFromReadTime(readTime, largestBatchId) {
|
|
4239
|
+
// We want to create an offset that matches all documents with a read time
|
|
4240
|
+
// greater than the provided read time. To do so, we technically need to
|
|
4241
|
+
// create an offset for `(readTime, MAX_DOCUMENT_KEY)`. While we could use
|
|
4242
|
+
// Unicode codepoints to generate MAX_DOCUMENT_KEY, it is much easier to use
|
|
4243
|
+
// `(readTime + 1, DocumentKey.empty())` since `> DocumentKey.empty()` matches
|
|
4244
|
+
// all valid document IDs.
|
|
4245
|
+
const successorSeconds = readTime.toTimestamp().seconds;
|
|
4246
|
+
const successorNanos = readTime.toTimestamp().nanoseconds + 1;
|
|
4247
|
+
const successor = SnapshotVersion.fromTimestamp(successorNanos === 1e9
|
|
4248
|
+
? new Timestamp(successorSeconds + 1, 0)
|
|
4249
|
+
: new Timestamp(successorSeconds, successorNanos));
|
|
4250
|
+
return new IndexOffset(successor, DocumentKey.empty(), largestBatchId);
|
|
4251
|
+
}
|
|
4252
|
+
/** Creates a new offset based on the provided document. */
|
|
4253
|
+
function newIndexOffsetFromDocument(document) {
|
|
4254
|
+
return new IndexOffset(document.readTime, document.key, INITIAL_LARGEST_BATCH_ID);
|
|
4255
|
+
}
|
|
4184
4256
|
/**
|
|
4185
4257
|
* Stores the latest read time, document and batch ID that were processed for an
|
|
4186
4258
|
* index.
|
|
@@ -4205,10 +4277,25 @@ class IndexOffset {
|
|
|
4205
4277
|
this.documentKey = documentKey;
|
|
4206
4278
|
this.largestBatchId = largestBatchId;
|
|
4207
4279
|
}
|
|
4208
|
-
/**
|
|
4280
|
+
/** Returns an offset that sorts before all regular offsets. */
|
|
4209
4281
|
static min() {
|
|
4210
4282
|
return new IndexOffset(SnapshotVersion.min(), DocumentKey.empty(), INITIAL_LARGEST_BATCH_ID);
|
|
4211
4283
|
}
|
|
4284
|
+
/** Returns an offset that sorts after all regular offsets. */
|
|
4285
|
+
static max() {
|
|
4286
|
+
return new IndexOffset(SnapshotVersion.max(), DocumentKey.empty(), INITIAL_LARGEST_BATCH_ID);
|
|
4287
|
+
}
|
|
4288
|
+
}
|
|
4289
|
+
function indexOffsetComparator(left, right) {
|
|
4290
|
+
let cmp = left.readTime.compareTo(right.readTime);
|
|
4291
|
+
if (cmp !== 0) {
|
|
4292
|
+
return cmp;
|
|
4293
|
+
}
|
|
4294
|
+
cmp = DocumentKey.comparator(left.documentKey, right.documentKey);
|
|
4295
|
+
if (cmp !== 0) {
|
|
4296
|
+
return cmp;
|
|
4297
|
+
}
|
|
4298
|
+
return primitiveComparator(left.largestBatchId, right.largestBatchId);
|
|
4212
4299
|
}
|
|
4213
4300
|
|
|
4214
4301
|
/**
|
|
@@ -5101,6 +5188,18 @@ function queryMatchesBounds(query, doc) {
|
|
|
5101
5188
|
}
|
|
5102
5189
|
return true;
|
|
5103
5190
|
}
|
|
5191
|
+
/**
|
|
5192
|
+
* Returns the collection group that this query targets.
|
|
5193
|
+
*
|
|
5194
|
+
* PORTING NOTE: This is only used in the Web SDK to facilitate multi-tab
|
|
5195
|
+
* synchronization for query results.
|
|
5196
|
+
*/
|
|
5197
|
+
function queryCollectionGroup(query) {
|
|
5198
|
+
return (query.collectionGroup ||
|
|
5199
|
+
(query.path.length % 2 === 1
|
|
5200
|
+
? query.path.lastSegment()
|
|
5201
|
+
: query.path.get(query.path.length - 2)));
|
|
5202
|
+
}
|
|
5104
5203
|
/**
|
|
5105
5204
|
* Returns a new comparator function that can be used to compare two documents
|
|
5106
5205
|
* based on the Query's ordering constraint.
|
|
@@ -8634,40 +8733,33 @@ function fromDbRemoteDocument(localSerializer, remoteDoc) {
|
|
|
8634
8733
|
}
|
|
8635
8734
|
/** Encodes a document for storage locally. */
|
|
8636
8735
|
function toDbRemoteDocument(localSerializer, document) {
|
|
8637
|
-
const
|
|
8638
|
-
const
|
|
8736
|
+
const key = document.key;
|
|
8737
|
+
const remoteDoc = {
|
|
8738
|
+
prefixPath: key.getCollectionPath().popLast().toArray(),
|
|
8739
|
+
collectionGroup: key.collectionGroup,
|
|
8740
|
+
documentId: key.path.lastSegment(),
|
|
8741
|
+
readTime: toDbTimestampKey(document.readTime),
|
|
8742
|
+
hasCommittedMutations: document.hasCommittedMutations
|
|
8743
|
+
};
|
|
8639
8744
|
if (document.isFoundDocument()) {
|
|
8640
|
-
|
|
8641
|
-
const hasCommittedMutations = document.hasCommittedMutations;
|
|
8642
|
-
return {
|
|
8643
|
-
document: doc,
|
|
8644
|
-
hasCommittedMutations,
|
|
8645
|
-
readTime,
|
|
8646
|
-
parentPath
|
|
8647
|
-
};
|
|
8745
|
+
remoteDoc.document = toDocument(localSerializer.remoteSerializer, document);
|
|
8648
8746
|
}
|
|
8649
8747
|
else if (document.isNoDocument()) {
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
noDocument: { path, readTime: toDbTimestamp(document.version) },
|
|
8654
|
-
hasCommittedMutations,
|
|
8655
|
-
readTime,
|
|
8656
|
-
parentPath
|
|
8748
|
+
remoteDoc.noDocument = {
|
|
8749
|
+
path: key.path.toArray(),
|
|
8750
|
+
readTime: toDbTimestamp(document.version)
|
|
8657
8751
|
};
|
|
8658
8752
|
}
|
|
8659
8753
|
else if (document.isUnknownDocument()) {
|
|
8660
|
-
|
|
8661
|
-
|
|
8662
|
-
|
|
8663
|
-
hasCommittedMutations: true,
|
|
8664
|
-
readTime,
|
|
8665
|
-
parentPath
|
|
8754
|
+
remoteDoc.unknownDocument = {
|
|
8755
|
+
path: key.path.toArray(),
|
|
8756
|
+
version: toDbTimestamp(document.version)
|
|
8666
8757
|
};
|
|
8667
8758
|
}
|
|
8668
8759
|
else {
|
|
8669
8760
|
return fail();
|
|
8670
8761
|
}
|
|
8762
|
+
return remoteDoc;
|
|
8671
8763
|
}
|
|
8672
8764
|
function toDbTimestampKey(snapshotVersion) {
|
|
8673
8765
|
const timestamp = snapshotVersion.toTimestamp();
|
|
@@ -11819,7 +11911,7 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
11819
11911
|
*/
|
|
11820
11912
|
addEntry(transaction, key, doc) {
|
|
11821
11913
|
const documentStore = remoteDocumentsStore(transaction);
|
|
11822
|
-
return documentStore.put(
|
|
11914
|
+
return documentStore.put(doc);
|
|
11823
11915
|
}
|
|
11824
11916
|
/**
|
|
11825
11917
|
* Removes a document from the cache.
|
|
@@ -11827,10 +11919,9 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
11827
11919
|
* All calls of `removeEntry` are required to go through the RemoteDocumentChangeBuffer
|
|
11828
11920
|
* returned by `newChangeBuffer()` to ensure proper accounting of metadata.
|
|
11829
11921
|
*/
|
|
11830
|
-
removeEntry(transaction, documentKey) {
|
|
11922
|
+
removeEntry(transaction, documentKey, readTime) {
|
|
11831
11923
|
const store = remoteDocumentsStore(transaction);
|
|
11832
|
-
|
|
11833
|
-
return store.delete(key);
|
|
11924
|
+
return store.delete(dbReadTimeKey(documentKey, readTime));
|
|
11834
11925
|
}
|
|
11835
11926
|
/**
|
|
11836
11927
|
* Updates the current cache size.
|
|
@@ -11845,11 +11936,15 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
11845
11936
|
});
|
|
11846
11937
|
}
|
|
11847
11938
|
getEntry(transaction, documentKey) {
|
|
11939
|
+
let doc = MutableDocument.newInvalidDocument(documentKey);
|
|
11848
11940
|
return remoteDocumentsStore(transaction)
|
|
11849
|
-
.
|
|
11850
|
-
|
|
11851
|
-
|
|
11852
|
-
})
|
|
11941
|
+
.iterate({
|
|
11942
|
+
index: DbRemoteDocumentDocumentKeyIndex,
|
|
11943
|
+
range: IDBKeyRange.only(dbKey(documentKey))
|
|
11944
|
+
}, (_, dbRemoteDoc) => {
|
|
11945
|
+
doc = this.maybeDecodeDocument(documentKey, dbRemoteDoc);
|
|
11946
|
+
})
|
|
11947
|
+
.next(() => doc);
|
|
11853
11948
|
}
|
|
11854
11949
|
/**
|
|
11855
11950
|
* Looks up an entry in the cache.
|
|
@@ -11858,15 +11953,21 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
11858
11953
|
* @returns The cached document entry and its size.
|
|
11859
11954
|
*/
|
|
11860
11955
|
getSizedEntry(transaction, documentKey) {
|
|
11956
|
+
let result = {
|
|
11957
|
+
size: 0,
|
|
11958
|
+
document: MutableDocument.newInvalidDocument(documentKey)
|
|
11959
|
+
};
|
|
11861
11960
|
return remoteDocumentsStore(transaction)
|
|
11862
|
-
.
|
|
11863
|
-
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11961
|
+
.iterate({
|
|
11962
|
+
index: DbRemoteDocumentDocumentKeyIndex,
|
|
11963
|
+
range: IDBKeyRange.only(dbKey(documentKey))
|
|
11964
|
+
}, (_, dbRemoteDoc) => {
|
|
11965
|
+
result = {
|
|
11966
|
+
document: this.maybeDecodeDocument(documentKey, dbRemoteDoc),
|
|
11867
11967
|
size: dbDocumentSize(dbRemoteDoc)
|
|
11868
11968
|
};
|
|
11869
|
-
})
|
|
11969
|
+
})
|
|
11970
|
+
.next(() => result);
|
|
11870
11971
|
}
|
|
11871
11972
|
getEntries(transaction, documentKeys) {
|
|
11872
11973
|
let results = mutableDocumentMap();
|
|
@@ -11897,14 +11998,20 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
11897
11998
|
if (documentKeys.isEmpty()) {
|
|
11898
11999
|
return PersistencePromise.resolve();
|
|
11899
12000
|
}
|
|
11900
|
-
|
|
11901
|
-
|
|
12001
|
+
let sortedKeys = new SortedSet(dbKeyComparator);
|
|
12002
|
+
documentKeys.forEach(e => (sortedKeys = sortedKeys.add(e)));
|
|
12003
|
+
const range = IDBKeyRange.bound(dbKey(sortedKeys.first()), dbKey(sortedKeys.last()));
|
|
12004
|
+
const keyIter = sortedKeys.getIterator();
|
|
11902
12005
|
let nextKey = keyIter.getNext();
|
|
11903
12006
|
return remoteDocumentsStore(transaction)
|
|
11904
|
-
.iterate({ range }, (
|
|
11905
|
-
const potentialKey = DocumentKey.fromSegments(
|
|
12007
|
+
.iterate({ index: DbRemoteDocumentDocumentKeyIndex, range }, (_, dbRemoteDoc, control) => {
|
|
12008
|
+
const potentialKey = DocumentKey.fromSegments([
|
|
12009
|
+
...dbRemoteDoc.prefixPath,
|
|
12010
|
+
dbRemoteDoc.collectionGroup,
|
|
12011
|
+
dbRemoteDoc.documentId
|
|
12012
|
+
]);
|
|
11906
12013
|
// Go through keys not found in cache.
|
|
11907
|
-
while (nextKey &&
|
|
12014
|
+
while (nextKey && dbKeyComparator(nextKey, potentialKey) < 0) {
|
|
11908
12015
|
callback(nextKey, null);
|
|
11909
12016
|
nextKey = keyIter.getNext();
|
|
11910
12017
|
}
|
|
@@ -11915,7 +12022,7 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
11915
12022
|
}
|
|
11916
12023
|
// Skip to the next key (if there is one).
|
|
11917
12024
|
if (nextKey) {
|
|
11918
|
-
control.skip(nextKey
|
|
12025
|
+
control.skip(dbKey(nextKey));
|
|
11919
12026
|
}
|
|
11920
12027
|
else {
|
|
11921
12028
|
control.done();
|
|
@@ -11930,41 +12037,44 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
11930
12037
|
}
|
|
11931
12038
|
});
|
|
11932
12039
|
}
|
|
11933
|
-
|
|
11934
|
-
|
|
11935
|
-
|
|
11936
|
-
|
|
11937
|
-
|
|
11938
|
-
|
|
11939
|
-
|
|
11940
|
-
|
|
11941
|
-
|
|
11942
|
-
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
|
|
11946
|
-
|
|
11947
|
-
|
|
11948
|
-
const readTimeKey = toDbTimestampKey(sinceReadTime);
|
|
11949
|
-
iterationOptions.range = IDBKeyRange.lowerBound([collectionKey, readTimeKey],
|
|
11950
|
-
/* open= */ true);
|
|
11951
|
-
iterationOptions.index = DbRemoteDocumentCollectionReadTimeIndex;
|
|
11952
|
-
}
|
|
12040
|
+
getAllFromCollection(transaction, collection, offset) {
|
|
12041
|
+
const startKey = [
|
|
12042
|
+
collection.popLast().toArray(),
|
|
12043
|
+
collection.lastSegment(),
|
|
12044
|
+
toDbTimestampKey(offset.readTime),
|
|
12045
|
+
offset.documentKey.path.isEmpty()
|
|
12046
|
+
? ''
|
|
12047
|
+
: offset.documentKey.path.lastSegment()
|
|
12048
|
+
];
|
|
12049
|
+
const endKey = [
|
|
12050
|
+
collection.popLast().toArray(),
|
|
12051
|
+
collection.lastSegment(),
|
|
12052
|
+
[Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER],
|
|
12053
|
+
''
|
|
12054
|
+
];
|
|
11953
12055
|
return remoteDocumentsStore(transaction)
|
|
11954
|
-
.
|
|
11955
|
-
|
|
11956
|
-
|
|
11957
|
-
|
|
11958
|
-
|
|
11959
|
-
// more than one segment longer than the query path.
|
|
11960
|
-
if (key.length !== immediateChildrenPathLength) {
|
|
11961
|
-
return;
|
|
11962
|
-
}
|
|
11963
|
-
const document = this.maybeDecodeDocument(DocumentKey.fromSegments(key), dbRemoteDoc);
|
|
11964
|
-
if (collection.isPrefixOf(document.key.path)) {
|
|
12056
|
+
.loadAll(IDBKeyRange.bound(startKey, endKey, true))
|
|
12057
|
+
.next(dbRemoteDocs => {
|
|
12058
|
+
let results = mutableDocumentMap();
|
|
12059
|
+
for (const dbRemoteDoc of dbRemoteDocs) {
|
|
12060
|
+
const document = this.maybeDecodeDocument(DocumentKey.fromSegments(dbRemoteDoc.prefixPath.concat(dbRemoteDoc.collectionGroup, dbRemoteDoc.documentId)), dbRemoteDoc);
|
|
11965
12061
|
results = results.insert(document.key, document);
|
|
11966
12062
|
}
|
|
11967
|
-
|
|
12063
|
+
return results;
|
|
12064
|
+
});
|
|
12065
|
+
}
|
|
12066
|
+
getAllFromCollectionGroup(transaction, collectionGroup, offset, limit) {
|
|
12067
|
+
let results = mutableDocumentMap();
|
|
12068
|
+
const startKey = dbCollectionGroupKey(collectionGroup, offset);
|
|
12069
|
+
const endKey = dbCollectionGroupKey(collectionGroup, IndexOffset.max());
|
|
12070
|
+
return remoteDocumentsStore(transaction)
|
|
12071
|
+
.iterate({
|
|
12072
|
+
index: DbRemoteDocumentCollectionGroupIndex,
|
|
12073
|
+
range: IDBKeyRange.bound(startKey, endKey, true)
|
|
12074
|
+
}, (_, dbRemoteDoc, control) => {
|
|
12075
|
+
const document = this.maybeDecodeDocument(DocumentKey.fromSegments(dbRemoteDoc.prefixPath.concat(dbRemoteDoc.collectionGroup, dbRemoteDoc.documentId)), dbRemoteDoc);
|
|
12076
|
+
results = results.insert(document.key, document);
|
|
12077
|
+
if (results.size === limit) {
|
|
11968
12078
|
control.done();
|
|
11969
12079
|
}
|
|
11970
12080
|
})
|
|
@@ -12008,50 +12118,6 @@ class IndexedDbRemoteDocumentCacheImpl {
|
|
|
12008
12118
|
function newIndexedDbRemoteDocumentCache(serializer) {
|
|
12009
12119
|
return new IndexedDbRemoteDocumentCacheImpl(serializer);
|
|
12010
12120
|
}
|
|
12011
|
-
/**
|
|
12012
|
-
* Returns the set of documents that have changed since the specified read
|
|
12013
|
-
* time.
|
|
12014
|
-
*/
|
|
12015
|
-
// PORTING NOTE: This is only used for multi-tab synchronization.
|
|
12016
|
-
function remoteDocumentCacheGetNewDocumentChanges(remoteDocumentCache, transaction, sinceReadTime) {
|
|
12017
|
-
const remoteDocumentCacheImpl = debugCast(remoteDocumentCache);
|
|
12018
|
-
let changedDocs = mutableDocumentMap();
|
|
12019
|
-
let lastReadTime = toDbTimestampKey(sinceReadTime);
|
|
12020
|
-
const documentsStore = remoteDocumentsStore(transaction);
|
|
12021
|
-
const range = IDBKeyRange.lowerBound(lastReadTime, true);
|
|
12022
|
-
return documentsStore
|
|
12023
|
-
.iterate({ index: DbRemoteDocumentReadTimeIndex, range }, (_, dbRemoteDoc) => {
|
|
12024
|
-
// Unlike `getEntry()` and others, `getNewDocumentChanges()` parses
|
|
12025
|
-
// the documents directly since we want to keep sentinel deletes.
|
|
12026
|
-
const doc = fromDbRemoteDocument(remoteDocumentCacheImpl.serializer, dbRemoteDoc);
|
|
12027
|
-
changedDocs = changedDocs.insert(doc.key, doc);
|
|
12028
|
-
lastReadTime = dbRemoteDoc.readTime;
|
|
12029
|
-
})
|
|
12030
|
-
.next(() => {
|
|
12031
|
-
return {
|
|
12032
|
-
changedDocs,
|
|
12033
|
-
readTime: fromDbTimestampKey(lastReadTime)
|
|
12034
|
-
};
|
|
12035
|
-
});
|
|
12036
|
-
}
|
|
12037
|
-
/**
|
|
12038
|
-
* Returns the read time of the most recently read document in the cache, or
|
|
12039
|
-
* SnapshotVersion.min() if not available.
|
|
12040
|
-
*/
|
|
12041
|
-
// PORTING NOTE: This is only used for multi-tab synchronization.
|
|
12042
|
-
function remoteDocumentCacheGetLastReadTime(transaction) {
|
|
12043
|
-
const documentsStore = remoteDocumentsStore(transaction);
|
|
12044
|
-
// If there are no existing entries, we return SnapshotVersion.min().
|
|
12045
|
-
let readTime = SnapshotVersion.min();
|
|
12046
|
-
return documentsStore
|
|
12047
|
-
.iterate({ index: DbRemoteDocumentReadTimeIndex, reverse: true }, (key, dbRemoteDoc, control) => {
|
|
12048
|
-
if (dbRemoteDoc.readTime) {
|
|
12049
|
-
readTime = fromDbTimestampKey(dbRemoteDoc.readTime);
|
|
12050
|
-
}
|
|
12051
|
-
control.done();
|
|
12052
|
-
})
|
|
12053
|
-
.next(() => readTime);
|
|
12054
|
-
}
|
|
12055
12121
|
/**
|
|
12056
12122
|
* Handles the details of adding and updating documents in the IndexedDbRemoteDocumentCache.
|
|
12057
12123
|
*
|
|
@@ -12069,24 +12135,26 @@ class IndexedDbRemoteDocumentChangeBuffer extends RemoteDocumentChangeBuffer {
|
|
|
12069
12135
|
super();
|
|
12070
12136
|
this.documentCache = documentCache;
|
|
12071
12137
|
this.trackRemovals = trackRemovals;
|
|
12072
|
-
// A map of document sizes prior to applying the changes in
|
|
12073
|
-
this
|
|
12138
|
+
// A map of document sizes and read times prior to applying the changes in
|
|
12139
|
+
// this buffer.
|
|
12140
|
+
this.documentStates = new ObjectMap(key => key.toString(), (l, r) => l.isEqual(r));
|
|
12074
12141
|
}
|
|
12075
12142
|
applyChanges(transaction) {
|
|
12076
12143
|
const promises = [];
|
|
12077
12144
|
let sizeDelta = 0;
|
|
12078
12145
|
let collectionParents = new SortedSet((l, r) => primitiveComparator(l.canonicalString(), r.canonicalString()));
|
|
12079
12146
|
this.changes.forEach((key, documentChange) => {
|
|
12080
|
-
const
|
|
12147
|
+
const previousDoc = this.documentStates.get(key);
|
|
12148
|
+
promises.push(this.documentCache.removeEntry(transaction, key, previousDoc.readTime));
|
|
12081
12149
|
if (documentChange.isValidDocument()) {
|
|
12082
12150
|
const doc = toDbRemoteDocument(this.documentCache.serializer, documentChange);
|
|
12083
12151
|
collectionParents = collectionParents.add(key.path.popLast());
|
|
12084
12152
|
const size = dbDocumentSize(doc);
|
|
12085
|
-
sizeDelta += size -
|
|
12153
|
+
sizeDelta += size - previousDoc.size;
|
|
12086
12154
|
promises.push(this.documentCache.addEntry(transaction, key, doc));
|
|
12087
12155
|
}
|
|
12088
12156
|
else {
|
|
12089
|
-
sizeDelta -=
|
|
12157
|
+
sizeDelta -= previousDoc.size;
|
|
12090
12158
|
if (this.trackRemovals) {
|
|
12091
12159
|
// In order to track removals, we store a "sentinel delete" in the
|
|
12092
12160
|
// RemoteDocumentCache. This entry is represented by a NoDocument
|
|
@@ -12095,9 +12163,6 @@ class IndexedDbRemoteDocumentChangeBuffer extends RemoteDocumentChangeBuffer {
|
|
|
12095
12163
|
const deletedDoc = toDbRemoteDocument(this.documentCache.serializer, documentChange.convertToNoDocument(SnapshotVersion.min()));
|
|
12096
12164
|
promises.push(this.documentCache.addEntry(transaction, key, deletedDoc));
|
|
12097
12165
|
}
|
|
12098
|
-
else {
|
|
12099
|
-
promises.push(this.documentCache.removeEntry(transaction, key));
|
|
12100
|
-
}
|
|
12101
12166
|
}
|
|
12102
12167
|
});
|
|
12103
12168
|
collectionParents.forEach(parent => {
|
|
@@ -12111,7 +12176,10 @@ class IndexedDbRemoteDocumentChangeBuffer extends RemoteDocumentChangeBuffer {
|
|
|
12111
12176
|
return this.documentCache
|
|
12112
12177
|
.getSizedEntry(transaction, documentKey)
|
|
12113
12178
|
.next(getResult => {
|
|
12114
|
-
this.
|
|
12179
|
+
this.documentStates.set(documentKey, {
|
|
12180
|
+
size: getResult.size,
|
|
12181
|
+
readTime: getResult.document.readTime
|
|
12182
|
+
});
|
|
12115
12183
|
return getResult.document;
|
|
12116
12184
|
});
|
|
12117
12185
|
}
|
|
@@ -12125,7 +12193,10 @@ class IndexedDbRemoteDocumentChangeBuffer extends RemoteDocumentChangeBuffer {
|
|
|
12125
12193
|
// keys to `DocumentSizeEntry`s. This is to allow returning the
|
|
12126
12194
|
// `MutableDocumentMap` directly, without a conversion.
|
|
12127
12195
|
sizeMap.forEach((documentKey, size) => {
|
|
12128
|
-
this.
|
|
12196
|
+
this.documentStates.set(documentKey, {
|
|
12197
|
+
size,
|
|
12198
|
+
readTime: documents.get(documentKey).readTime
|
|
12199
|
+
});
|
|
12129
12200
|
});
|
|
12130
12201
|
return documents;
|
|
12131
12202
|
});
|
|
@@ -12140,8 +12211,52 @@ function documentGlobalStore(txn) {
|
|
|
12140
12211
|
function remoteDocumentsStore(txn) {
|
|
12141
12212
|
return getStore(txn, DbRemoteDocumentStore);
|
|
12142
12213
|
}
|
|
12143
|
-
|
|
12144
|
-
|
|
12214
|
+
/**
|
|
12215
|
+
* Returns a key that can be used for document lookups on the
|
|
12216
|
+
* `DbRemoteDocumentDocumentKeyIndex` index.
|
|
12217
|
+
*/
|
|
12218
|
+
function dbKey(documentKey) {
|
|
12219
|
+
const path = documentKey.path.toArray();
|
|
12220
|
+
return [
|
|
12221
|
+
/* prefix path */ path.slice(0, path.length - 2),
|
|
12222
|
+
/* collection id */ path[path.length - 2],
|
|
12223
|
+
/* document id */ path[path.length - 1]
|
|
12224
|
+
];
|
|
12225
|
+
}
|
|
12226
|
+
/**
|
|
12227
|
+
* Returns a key that can be used for document lookups via the primary key of
|
|
12228
|
+
* the DbRemoteDocument object store.
|
|
12229
|
+
*/
|
|
12230
|
+
function dbReadTimeKey(documentKey, readTime) {
|
|
12231
|
+
const path = documentKey.path.toArray();
|
|
12232
|
+
return [
|
|
12233
|
+
/* prefix path */ path.slice(0, path.length - 2),
|
|
12234
|
+
/* collection id */ path[path.length - 2],
|
|
12235
|
+
toDbTimestampKey(readTime),
|
|
12236
|
+
/* document id */ path[path.length - 1]
|
|
12237
|
+
];
|
|
12238
|
+
}
|
|
12239
|
+
/**
|
|
12240
|
+
* Returns a key that can be used for document lookups on the
|
|
12241
|
+
* `DbRemoteDocumentDocumentCollectionGroupIndex` index.
|
|
12242
|
+
*/
|
|
12243
|
+
function dbCollectionGroupKey(collectionGroup, offset) {
|
|
12244
|
+
const path = offset.documentKey.path.toArray();
|
|
12245
|
+
return [
|
|
12246
|
+
/* collection id */ collectionGroup,
|
|
12247
|
+
toDbTimestampKey(offset.readTime),
|
|
12248
|
+
/* prefix path */ path.slice(0, path.length - 2),
|
|
12249
|
+
/* document id */ path.length > 0 ? path[path.length - 1] : ''
|
|
12250
|
+
];
|
|
12251
|
+
}
|
|
12252
|
+
/**
|
|
12253
|
+
* Comparator that compares document keys according to the primary key sorting
|
|
12254
|
+
* used by the `DbRemoteDocumentDocument` store (by collection path and then
|
|
12255
|
+
* document ID).
|
|
12256
|
+
*/
|
|
12257
|
+
function dbKeyComparator(l, r) {
|
|
12258
|
+
const cmp = l.path.length - r.path.length;
|
|
12259
|
+
return cmp !== 0 ? cmp : DocumentKey.comparator(l, r);
|
|
12145
12260
|
}
|
|
12146
12261
|
/**
|
|
12147
12262
|
* Schema Version for the Web client:
|
|
@@ -12162,9 +12277,11 @@ function dbKey(docKey) {
|
|
|
12162
12277
|
* 10. Rewrite the canonical IDs to the explicit Protobuf-based format.
|
|
12163
12278
|
* 11. Add bundles and named_queries for bundle support.
|
|
12164
12279
|
* 12. Add document overlays.
|
|
12165
|
-
* 13.
|
|
12280
|
+
* 13. Rewrite the keys of the remote document cache to allow for efficient
|
|
12281
|
+
* document lookup via `getAll()`.
|
|
12282
|
+
* 14. Add indexing support.
|
|
12166
12283
|
*/
|
|
12167
|
-
const SCHEMA_VERSION =
|
|
12284
|
+
const SCHEMA_VERSION = 13;
|
|
12168
12285
|
|
|
12169
12286
|
/**
|
|
12170
12287
|
* @license
|
|
@@ -12200,7 +12317,7 @@ class SchemaConverter {
|
|
|
12200
12317
|
createPrimaryClientStore(db);
|
|
12201
12318
|
createMutationQueue(db);
|
|
12202
12319
|
createQueryCache(db);
|
|
12203
|
-
|
|
12320
|
+
createLegacyRemoteDocumentCache(db);
|
|
12204
12321
|
}
|
|
12205
12322
|
// Migration 2 to populate the targetGlobal object no longer needed since
|
|
12206
12323
|
// migration 3 unconditionally clears it.
|
|
@@ -12249,7 +12366,8 @@ class SchemaConverter {
|
|
|
12249
12366
|
// to the DbRemoteDocument object store itself. Since the previous change
|
|
12250
12367
|
// log only contained transient data, we can drop its object store.
|
|
12251
12368
|
dropRemoteDocumentChangesStore(db);
|
|
12252
|
-
|
|
12369
|
+
// Note: Schema version 9 used to create a read time index for the
|
|
12370
|
+
// RemoteDocumentCache. This is now done with schema version 13.
|
|
12253
12371
|
});
|
|
12254
12372
|
}
|
|
12255
12373
|
if (fromVersion < 10 && toVersion >= 10) {
|
|
@@ -12267,6 +12385,12 @@ class SchemaConverter {
|
|
|
12267
12385
|
});
|
|
12268
12386
|
}
|
|
12269
12387
|
if (fromVersion < 13 && toVersion >= 13) {
|
|
12388
|
+
p = p
|
|
12389
|
+
.next(() => createRemoteDocumentCache(db))
|
|
12390
|
+
.next(() => this.rewriteRemoteDocumentCache(db, simpleDbTransaction))
|
|
12391
|
+
.next(() => db.deleteObjectStore(DbRemoteDocumentStore$1));
|
|
12392
|
+
}
|
|
12393
|
+
if (fromVersion < 14 && toVersion >= 14) {
|
|
12270
12394
|
p = p.next(() => {
|
|
12271
12395
|
createFieldIndex(db);
|
|
12272
12396
|
});
|
|
@@ -12276,7 +12400,7 @@ class SchemaConverter {
|
|
|
12276
12400
|
addDocumentGlobal(txn) {
|
|
12277
12401
|
let byteSize = 0;
|
|
12278
12402
|
return txn
|
|
12279
|
-
.store(DbRemoteDocumentStore)
|
|
12403
|
+
.store(DbRemoteDocumentStore$1)
|
|
12280
12404
|
.iterate((_, doc) => {
|
|
12281
12405
|
byteSize += dbDocumentSize(doc);
|
|
12282
12406
|
})
|
|
@@ -12311,7 +12435,7 @@ class SchemaConverter {
|
|
|
12311
12435
|
*/
|
|
12312
12436
|
ensureSequenceNumbers(txn) {
|
|
12313
12437
|
const documentTargetStore = txn.store(DbTargetDocumentStore);
|
|
12314
|
-
const documentsStore = txn.store(DbRemoteDocumentStore);
|
|
12438
|
+
const documentsStore = txn.store(DbRemoteDocumentStore$1);
|
|
12315
12439
|
const globalTargetStore = txn.store(DbTargetGlobalStore);
|
|
12316
12440
|
return globalTargetStore.get(DbTargetGlobalKey).next(metadata => {
|
|
12317
12441
|
const writeSentinelKey = (path) => {
|
|
@@ -12358,7 +12482,7 @@ class SchemaConverter {
|
|
|
12358
12482
|
};
|
|
12359
12483
|
// Index existing remote documents.
|
|
12360
12484
|
return txn
|
|
12361
|
-
.store(DbRemoteDocumentStore)
|
|
12485
|
+
.store(DbRemoteDocumentStore$1)
|
|
12362
12486
|
.iterate({ keysOnly: true }, (pathSegments, _) => {
|
|
12363
12487
|
const path = new ResourcePath(pathSegments);
|
|
12364
12488
|
return addEntry(path.popLast());
|
|
@@ -12381,6 +12505,27 @@ class SchemaConverter {
|
|
|
12381
12505
|
return targetStore.put(updatedDbTarget);
|
|
12382
12506
|
});
|
|
12383
12507
|
}
|
|
12508
|
+
rewriteRemoteDocumentCache(db, transaction) {
|
|
12509
|
+
const legacyRemoteDocumentStore = transaction.store(DbRemoteDocumentStore$1);
|
|
12510
|
+
const writes = [];
|
|
12511
|
+
return legacyRemoteDocumentStore
|
|
12512
|
+
.iterate((_, legacyDocument) => {
|
|
12513
|
+
const remoteDocumentStore = transaction.store(DbRemoteDocumentStore);
|
|
12514
|
+
const path = extractKey(legacyDocument).path.toArray();
|
|
12515
|
+
const dbRemoteDocument = {
|
|
12516
|
+
prefixPath: path.slice(0, path.length - 2),
|
|
12517
|
+
collectionGroup: path[path.length - 2],
|
|
12518
|
+
documentId: path[path.length - 1],
|
|
12519
|
+
readTime: legacyDocument.readTime || [0, 0],
|
|
12520
|
+
unknownDocument: legacyDocument.unknownDocument,
|
|
12521
|
+
noDocument: legacyDocument.noDocument,
|
|
12522
|
+
document: legacyDocument.document,
|
|
12523
|
+
hasCommittedMutations: !!legacyDocument.hasCommittedMutations
|
|
12524
|
+
};
|
|
12525
|
+
writes.push(remoteDocumentStore.put(dbRemoteDocument));
|
|
12526
|
+
})
|
|
12527
|
+
.next(() => PersistencePromise.waitFor(writes));
|
|
12528
|
+
}
|
|
12384
12529
|
}
|
|
12385
12530
|
function sentinelKey(path) {
|
|
12386
12531
|
return [0, encodeResourcePath(path)];
|
|
@@ -12417,8 +12562,15 @@ function upgradeMutationBatchSchemaAndMigrateData(db, txn) {
|
|
|
12417
12562
|
return PersistencePromise.waitFor(writeAll);
|
|
12418
12563
|
});
|
|
12419
12564
|
}
|
|
12565
|
+
function createLegacyRemoteDocumentCache(db) {
|
|
12566
|
+
db.createObjectStore(DbRemoteDocumentStore$1);
|
|
12567
|
+
}
|
|
12420
12568
|
function createRemoteDocumentCache(db) {
|
|
12421
|
-
db.createObjectStore(DbRemoteDocumentStore
|
|
12569
|
+
const remoteDocumentStore = db.createObjectStore(DbRemoteDocumentStore, {
|
|
12570
|
+
keyPath: DbRemoteDocumentKeyPath
|
|
12571
|
+
});
|
|
12572
|
+
remoteDocumentStore.createIndex(DbRemoteDocumentDocumentKeyIndex, DbRemoteDocumentDocumentKeyIndexPath);
|
|
12573
|
+
remoteDocumentStore.createIndex(DbRemoteDocumentCollectionGroupIndex, DbRemoteDocumentCollectionGroupIndexPath);
|
|
12422
12574
|
}
|
|
12423
12575
|
function createDocumentGlobalStore(db) {
|
|
12424
12576
|
db.createObjectStore(DbRemoteDocumentGlobalStore);
|
|
@@ -12460,15 +12612,6 @@ function writeEmptyTargetGlobalEntry(txn) {
|
|
|
12460
12612
|
};
|
|
12461
12613
|
return globalStore.put(DbTargetGlobalKey, metadata);
|
|
12462
12614
|
}
|
|
12463
|
-
/**
|
|
12464
|
-
* Creates indices on the RemoteDocuments store used for both multi-tab
|
|
12465
|
-
* and Index-Free queries.
|
|
12466
|
-
*/
|
|
12467
|
-
function createRemoteDocumentReadTimeIndex(txn) {
|
|
12468
|
-
const remoteDocumentStore = txn.objectStore(DbRemoteDocumentStore);
|
|
12469
|
-
remoteDocumentStore.createIndex(DbRemoteDocumentReadTimeIndex, DbRemoteDocumentReadTimeIndexPath, { unique: false });
|
|
12470
|
-
remoteDocumentStore.createIndex(DbRemoteDocumentCollectionReadTimeIndex, DbRemoteDocumentCollectionReadTimeIndexPath, { unique: false });
|
|
12471
|
-
}
|
|
12472
12615
|
function createClientMetadataStore(db) {
|
|
12473
12616
|
db.createObjectStore(DbClientMetadataStore, {
|
|
12474
12617
|
keyPath: DbClientMetadataKeyPath
|
|
@@ -12485,11 +12628,11 @@ function createNamedQueriesStore(db) {
|
|
|
12485
12628
|
});
|
|
12486
12629
|
}
|
|
12487
12630
|
function createFieldIndex(db) {
|
|
12488
|
-
const
|
|
12631
|
+
const indexConfigurationStore = db.createObjectStore(DbIndexConfigurationStore, {
|
|
12489
12632
|
keyPath: DbIndexConfigurationKeyPath,
|
|
12490
12633
|
autoIncrement: true
|
|
12491
12634
|
});
|
|
12492
|
-
|
|
12635
|
+
indexConfigurationStore.createIndex(DbIndexConfigurationCollectionGroupIndex, DbIndexConfigurationCollectionGroupIndexPath, { unique: false });
|
|
12493
12636
|
const indexStateStore = db.createObjectStore(DbIndexStateStore, {
|
|
12494
12637
|
keyPath: DbIndexStateKeyPath
|
|
12495
12638
|
});
|
|
@@ -12505,6 +12648,20 @@ function createDocumentOverlayStore(db) {
|
|
|
12505
12648
|
});
|
|
12506
12649
|
documentOverlayStore.createIndex(DbDocumentOverlayCollectionPathOverlayIndex, DbDocumentOverlayCollectionPathOverlayIndexPath, { unique: false });
|
|
12507
12650
|
documentOverlayStore.createIndex(DbDocumentOverlayCollectionGroupOverlayIndex, DbDocumentOverlayCollectionGroupOverlayIndexPath, { unique: false });
|
|
12651
|
+
}
|
|
12652
|
+
function extractKey(remoteDoc) {
|
|
12653
|
+
if (remoteDoc.document) {
|
|
12654
|
+
return new DocumentKey(ResourcePath.fromString(remoteDoc.document.name).popFirst(5));
|
|
12655
|
+
}
|
|
12656
|
+
else if (remoteDoc.noDocument) {
|
|
12657
|
+
return DocumentKey.fromSegments(remoteDoc.noDocument.path);
|
|
12658
|
+
}
|
|
12659
|
+
else if (remoteDoc.unknownDocument) {
|
|
12660
|
+
return DocumentKey.fromSegments(remoteDoc.unknownDocument.path);
|
|
12661
|
+
}
|
|
12662
|
+
else {
|
|
12663
|
+
return fail();
|
|
12664
|
+
}
|
|
12508
12665
|
}
|
|
12509
12666
|
|
|
12510
12667
|
/**
|
|
@@ -13347,18 +13504,17 @@ class LocalDocumentsView {
|
|
|
13347
13504
|
*
|
|
13348
13505
|
* @param transaction - The persistence transaction.
|
|
13349
13506
|
* @param query - The query to match documents against.
|
|
13350
|
-
* @param
|
|
13351
|
-
* documents that have been read since this snapshot version (exclusive).
|
|
13507
|
+
* @param offset - Read time and key to start scanning by (exclusive).
|
|
13352
13508
|
*/
|
|
13353
|
-
getDocumentsMatchingQuery(transaction, query,
|
|
13509
|
+
getDocumentsMatchingQuery(transaction, query, offset) {
|
|
13354
13510
|
if (isDocumentQuery$1(query)) {
|
|
13355
13511
|
return this.getDocumentsMatchingDocumentQuery(transaction, query.path);
|
|
13356
13512
|
}
|
|
13357
13513
|
else if (isCollectionGroupQuery(query)) {
|
|
13358
|
-
return this.getDocumentsMatchingCollectionGroupQuery(transaction, query,
|
|
13514
|
+
return this.getDocumentsMatchingCollectionGroupQuery(transaction, query, offset);
|
|
13359
13515
|
}
|
|
13360
13516
|
else {
|
|
13361
|
-
return this.getDocumentsMatchingCollectionQuery(transaction, query,
|
|
13517
|
+
return this.getDocumentsMatchingCollectionQuery(transaction, query, offset);
|
|
13362
13518
|
}
|
|
13363
13519
|
}
|
|
13364
13520
|
getDocumentsMatchingDocumentQuery(transaction, docPath) {
|
|
@@ -13371,7 +13527,7 @@ class LocalDocumentsView {
|
|
|
13371
13527
|
return result;
|
|
13372
13528
|
});
|
|
13373
13529
|
}
|
|
13374
|
-
getDocumentsMatchingCollectionGroupQuery(transaction, query,
|
|
13530
|
+
getDocumentsMatchingCollectionGroupQuery(transaction, query, offset) {
|
|
13375
13531
|
const collectionId = query.collectionGroup;
|
|
13376
13532
|
let results = documentMap();
|
|
13377
13533
|
return this.indexManager
|
|
@@ -13381,7 +13537,7 @@ class LocalDocumentsView {
|
|
|
13381
13537
|
// collectionId and aggregate the results.
|
|
13382
13538
|
return PersistencePromise.forEach(parents, (parent) => {
|
|
13383
13539
|
const collectionQuery = asCollectionQueryAtPath(query, parent.child(collectionId));
|
|
13384
|
-
return this.getDocumentsMatchingCollectionQuery(transaction, collectionQuery,
|
|
13540
|
+
return this.getDocumentsMatchingCollectionQuery(transaction, collectionQuery, offset).next(r => {
|
|
13385
13541
|
r.forEach((key, doc) => {
|
|
13386
13542
|
results = results.insert(key, doc);
|
|
13387
13543
|
});
|
|
@@ -13389,11 +13545,11 @@ class LocalDocumentsView {
|
|
|
13389
13545
|
}).next(() => results);
|
|
13390
13546
|
});
|
|
13391
13547
|
}
|
|
13392
|
-
getDocumentsMatchingCollectionQuery(transaction, query,
|
|
13548
|
+
getDocumentsMatchingCollectionQuery(transaction, query, offset) {
|
|
13393
13549
|
// Query the remote documents and overlay mutations.
|
|
13394
13550
|
let results;
|
|
13395
13551
|
return this.remoteDocumentCache
|
|
13396
|
-
.
|
|
13552
|
+
.getAllFromCollection(transaction, query.path, offset)
|
|
13397
13553
|
.next(queryResults => {
|
|
13398
13554
|
results = queryResults;
|
|
13399
13555
|
return this.mutationQueue.getAllMutationBatchesAffectingQuery(transaction, query);
|
|
@@ -13479,11 +13635,12 @@ class LocalStoreImpl {
|
|
|
13479
13635
|
// TODO(wuandy): Evaluate if TargetId can be part of Target.
|
|
13480
13636
|
this.targetIdByTarget = new ObjectMap(t => canonifyTarget(t), targetEquals);
|
|
13481
13637
|
/**
|
|
13482
|
-
*
|
|
13638
|
+
* A per collection group index of the last read time processed by
|
|
13639
|
+
* `getNewDocumentChanges()`.
|
|
13483
13640
|
*
|
|
13484
13641
|
* PORTING NOTE: This is only used for multi-tab synchronization.
|
|
13485
13642
|
*/
|
|
13486
|
-
this.
|
|
13643
|
+
this.collectionGroupReadTime = new Map();
|
|
13487
13644
|
this.remoteDocuments = persistence.getRemoteDocumentCache();
|
|
13488
13645
|
this.targetCache = persistence.getTargetCache();
|
|
13489
13646
|
this.bundleCache = persistence.getBundleCache();
|
|
@@ -14018,6 +14175,7 @@ function localStoreExecuteQuery(localStore, query, usePreviousResults) {
|
|
|
14018
14175
|
? lastLimboFreeSnapshotVersion
|
|
14019
14176
|
: SnapshotVersion.min(), usePreviousResults ? remoteKeys : documentKeySet()))
|
|
14020
14177
|
.next(documents => {
|
|
14178
|
+
setMaxReadTime(localStoreImpl, queryCollectionGroup(query), documents);
|
|
14021
14179
|
return { documents, remoteKeys };
|
|
14022
14180
|
});
|
|
14023
14181
|
});
|
|
@@ -14095,28 +14253,32 @@ function localStoreGetCachedTarget(localStore, targetId) {
|
|
|
14095
14253
|
* since the prior call.
|
|
14096
14254
|
*/
|
|
14097
14255
|
// PORTING NOTE: Multi-Tab only.
|
|
14098
|
-
function localStoreGetNewDocumentChanges(localStore) {
|
|
14256
|
+
function localStoreGetNewDocumentChanges(localStore, collectionGroup) {
|
|
14099
14257
|
const localStoreImpl = debugCast(localStore);
|
|
14258
|
+
// Get the current maximum read time for the collection. This should always
|
|
14259
|
+
// exist, but to reduce the chance for regressions we default to
|
|
14260
|
+
// SnapshotVersion.Min()
|
|
14261
|
+
// TODO(indexing): Consider removing the default value.
|
|
14262
|
+
const readTime = localStoreImpl.collectionGroupReadTime.get(collectionGroup) ||
|
|
14263
|
+
SnapshotVersion.min();
|
|
14100
14264
|
return localStoreImpl.persistence
|
|
14101
|
-
.runTransaction('Get new document changes', 'readonly', txn =>
|
|
14102
|
-
|
|
14103
|
-
|
|
14265
|
+
.runTransaction('Get new document changes', 'readonly', txn => localStoreImpl.remoteDocuments.getAllFromCollectionGroup(txn, collectionGroup, newIndexOffsetSuccessorFromReadTime(readTime, INITIAL_LARGEST_BATCH_ID),
|
|
14266
|
+
/* limit= */ Number.MAX_SAFE_INTEGER))
|
|
14267
|
+
.then(changedDocs => {
|
|
14268
|
+
setMaxReadTime(localStoreImpl, collectionGroup, changedDocs);
|
|
14104
14269
|
return changedDocs;
|
|
14105
14270
|
});
|
|
14106
14271
|
}
|
|
14107
|
-
/**
|
|
14108
|
-
* Reads the newest document change from persistence and moves the internal
|
|
14109
|
-
* synchronization marker forward so that calls to `getNewDocumentChanges()`
|
|
14110
|
-
* only return changes that happened after client initialization.
|
|
14111
|
-
*/
|
|
14272
|
+
/** Sets the collection group's maximum read time from the given documents. */
|
|
14112
14273
|
// PORTING NOTE: Multi-Tab only.
|
|
14113
|
-
|
|
14114
|
-
|
|
14115
|
-
|
|
14116
|
-
.
|
|
14117
|
-
|
|
14118
|
-
|
|
14274
|
+
function setMaxReadTime(localStoreImpl, collectionGroup, changedDocs) {
|
|
14275
|
+
let readTime = SnapshotVersion.min();
|
|
14276
|
+
changedDocs.forEach((_, doc) => {
|
|
14277
|
+
if (doc.readTime.compareTo(readTime) > 0) {
|
|
14278
|
+
readTime = doc.readTime;
|
|
14279
|
+
}
|
|
14119
14280
|
});
|
|
14281
|
+
localStoreImpl.collectionGroupReadTime.set(collectionGroup, readTime);
|
|
14120
14282
|
}
|
|
14121
14283
|
/**
|
|
14122
14284
|
* Creates a new target using the given bundle name, which will be used to
|
|
@@ -14799,7 +14961,7 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
14799
14961
|
});
|
|
14800
14962
|
return PersistencePromise.resolve(results);
|
|
14801
14963
|
}
|
|
14802
|
-
|
|
14964
|
+
getAllFromCollection(transaction, collectionPath, offset) {
|
|
14803
14965
|
let results = mutableDocumentMap();
|
|
14804
14966
|
// Documents are ordered by key, so we can use a prefix scan to narrow down
|
|
14805
14967
|
// the documents we need to match the query against.
|
|
@@ -14814,13 +14976,19 @@ class MemoryRemoteDocumentCacheImpl {
|
|
|
14814
14976
|
// Exclude entries from subcollections.
|
|
14815
14977
|
continue;
|
|
14816
14978
|
}
|
|
14817
|
-
if (document
|
|
14979
|
+
if (indexOffsetComparator(newIndexOffsetFromDocument(document), offset) <= 0) {
|
|
14980
|
+
// The document sorts before the offset.
|
|
14818
14981
|
continue;
|
|
14819
14982
|
}
|
|
14820
14983
|
results = results.insert(document.key, document.mutableCopy());
|
|
14821
14984
|
}
|
|
14822
14985
|
return PersistencePromise.resolve(results);
|
|
14823
14986
|
}
|
|
14987
|
+
getAllFromCollectionGroup(transaction, collectionGroup, offset, limti) {
|
|
14988
|
+
// This method should only be called from the IndexBackfiller if persistence
|
|
14989
|
+
// is enabled.
|
|
14990
|
+
fail();
|
|
14991
|
+
}
|
|
14824
14992
|
forEachDocumentKey(transaction, f) {
|
|
14825
14993
|
return PersistencePromise.forEach(this.docs, (key) => f(key));
|
|
14826
14994
|
}
|
|
@@ -15273,7 +15441,7 @@ class QueryEngine {
|
|
|
15273
15441
|
}
|
|
15274
15442
|
// Retrieve all results for documents that were updated since the last
|
|
15275
15443
|
// limbo-document free remote snapshot.
|
|
15276
|
-
return this.localDocumentsView.getDocumentsMatchingQuery(transaction, query, lastLimboFreeSnapshotVersion).next(updatedResults => {
|
|
15444
|
+
return this.localDocumentsView.getDocumentsMatchingQuery(transaction, query, newIndexOffsetSuccessorFromReadTime(lastLimboFreeSnapshotVersion, INITIAL_LARGEST_BATCH_ID)).next(updatedResults => {
|
|
15277
15445
|
// We merge `previousResults` into `updateResults`, since
|
|
15278
15446
|
// `updateResults` is already a DocumentMap. If a document is
|
|
15279
15447
|
// contained in both lists, then its contents are the same.
|
|
@@ -15335,7 +15503,7 @@ class QueryEngine {
|
|
|
15335
15503
|
if (getLogLevel() <= LogLevel.DEBUG) {
|
|
15336
15504
|
logDebug('QueryEngine', 'Using full collection scan to execute query:', stringifyQuery(query));
|
|
15337
15505
|
}
|
|
15338
|
-
return this.localDocumentsView.getDocumentsMatchingQuery(transaction, query,
|
|
15506
|
+
return this.localDocumentsView.getDocumentsMatchingQuery(transaction, query, IndexOffset.min());
|
|
15339
15507
|
}
|
|
15340
15508
|
}
|
|
15341
15509
|
|
|
@@ -15396,8 +15564,9 @@ function createWebStorageOnlineStateKey(persistenceKey) {
|
|
|
15396
15564
|
// The WebStorage prefix that plays as a event to indicate the remote documents
|
|
15397
15565
|
// might have changed due to some secondary tabs loading a bundle.
|
|
15398
15566
|
// format of the key is:
|
|
15399
|
-
//
|
|
15400
|
-
|
|
15567
|
+
// firestore_bundle_loaded_v2_<persistenceKey>
|
|
15568
|
+
// The version ending with "v2" stores the list of modified collection groups.
|
|
15569
|
+
const BUNDLE_LOADED_KEY_PREFIX = 'firestore_bundle_loaded_v2';
|
|
15401
15570
|
function createBundleLoadedKey(persistenceKey) {
|
|
15402
15571
|
return `${BUNDLE_LOADED_KEY_PREFIX}_${persistenceKey}`;
|
|
15403
15572
|
}
|
|
@@ -15775,8 +15944,8 @@ class WebStorageSharedClientState {
|
|
|
15775
15944
|
setOnlineState(onlineState) {
|
|
15776
15945
|
this.persistOnlineState(onlineState);
|
|
15777
15946
|
}
|
|
15778
|
-
notifyBundleLoaded() {
|
|
15779
|
-
this.persistBundleLoadedState();
|
|
15947
|
+
notifyBundleLoaded(collectionGroups) {
|
|
15948
|
+
this.persistBundleLoadedState(collectionGroups);
|
|
15780
15949
|
}
|
|
15781
15950
|
shutdown() {
|
|
15782
15951
|
if (this.started) {
|
|
@@ -15860,7 +16029,8 @@ class WebStorageSharedClientState {
|
|
|
15860
16029
|
}
|
|
15861
16030
|
}
|
|
15862
16031
|
else if (storageEvent.key === this.bundleLoadedKey) {
|
|
15863
|
-
|
|
16032
|
+
const collectionGroups = this.fromWebStoreBundleLoadedState(storageEvent.newValue);
|
|
16033
|
+
await Promise.all(collectionGroups.map(cg => this.syncEngine.synchronizeWithChangedDocuments(cg)));
|
|
15864
16034
|
}
|
|
15865
16035
|
});
|
|
15866
16036
|
}
|
|
@@ -15892,8 +16062,9 @@ class WebStorageSharedClientState {
|
|
|
15892
16062
|
const targetMetadata = new QueryTargetMetadata(targetId, state, error);
|
|
15893
16063
|
this.setItem(targetKey, targetMetadata.toWebStorageJSON());
|
|
15894
16064
|
}
|
|
15895
|
-
persistBundleLoadedState() {
|
|
15896
|
-
|
|
16065
|
+
persistBundleLoadedState(collectionGroups) {
|
|
16066
|
+
const json = JSON.stringify(Array.from(collectionGroups));
|
|
16067
|
+
this.setItem(this.bundleLoadedKey, json);
|
|
15897
16068
|
}
|
|
15898
16069
|
/**
|
|
15899
16070
|
* Parses a client state key in WebStorage. Returns null if the key does not
|
|
@@ -15937,6 +16108,9 @@ class WebStorageSharedClientState {
|
|
|
15937
16108
|
fromWebStorageOnlineState(value) {
|
|
15938
16109
|
return SharedOnlineState.fromWebStorageEntry(value);
|
|
15939
16110
|
}
|
|
16111
|
+
fromWebStoreBundleLoadedState(value) {
|
|
16112
|
+
return JSON.parse(value);
|
|
16113
|
+
}
|
|
15940
16114
|
async handleMutationBatchEvent(mutationBatch) {
|
|
15941
16115
|
if (mutationBatch.user.uid !== this.currentUser.uid) {
|
|
15942
16116
|
logDebug(LOG_TAG$a, `Ignoring mutation for non-active user ${mutationBatch.user.uid}`);
|
|
@@ -16053,7 +16227,7 @@ class MemorySharedClientState {
|
|
|
16053
16227
|
}
|
|
16054
16228
|
shutdown() { }
|
|
16055
16229
|
writeSequenceNumber(sequenceNumber) { }
|
|
16056
|
-
notifyBundleLoaded() {
|
|
16230
|
+
notifyBundleLoaded(collectionGroups) {
|
|
16057
16231
|
// No op.
|
|
16058
16232
|
}
|
|
16059
16233
|
}
|
|
@@ -21353,29 +21527,6 @@ class LocalViewChanges {
|
|
|
21353
21527
|
}
|
|
21354
21528
|
}
|
|
21355
21529
|
|
|
21356
|
-
/**
|
|
21357
|
-
* @license
|
|
21358
|
-
* Copyright 2020 Google LLC
|
|
21359
|
-
*
|
|
21360
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
21361
|
-
* you may not use this file except in compliance with the License.
|
|
21362
|
-
* You may obtain a copy of the License at
|
|
21363
|
-
*
|
|
21364
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
21365
|
-
*
|
|
21366
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
21367
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
21368
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21369
|
-
* See the License for the specific language governing permissions and
|
|
21370
|
-
* limitations under the License.
|
|
21371
|
-
*/
|
|
21372
|
-
class BundleLoadResult {
|
|
21373
|
-
constructor(progress, changedDocs) {
|
|
21374
|
-
this.progress = progress;
|
|
21375
|
-
this.changedDocs = changedDocs;
|
|
21376
|
-
}
|
|
21377
|
-
}
|
|
21378
|
-
|
|
21379
21530
|
/**
|
|
21380
21531
|
* @license
|
|
21381
21532
|
* Copyright 2020 Google LLC
|
|
@@ -21430,6 +21581,8 @@ class BundleLoader {
|
|
|
21430
21581
|
this.queries = [];
|
|
21431
21582
|
/** Batched documents to be saved into storage */
|
|
21432
21583
|
this.documents = [];
|
|
21584
|
+
/** The collection groups affected by this bundle. */
|
|
21585
|
+
this.collectionGroups = new Set();
|
|
21433
21586
|
this.progress = bundleInitialProgress(bundleMetadata);
|
|
21434
21587
|
}
|
|
21435
21588
|
/**
|
|
@@ -21449,6 +21602,8 @@ class BundleLoader {
|
|
|
21449
21602
|
if (!element.payload.documentMetadata.exists) {
|
|
21450
21603
|
++documentsLoaded;
|
|
21451
21604
|
}
|
|
21605
|
+
const path = ResourcePath.fromString(element.payload.documentMetadata.name);
|
|
21606
|
+
this.collectionGroups.add(path.get(path.length - 2));
|
|
21452
21607
|
}
|
|
21453
21608
|
else if (element.payload.document) {
|
|
21454
21609
|
this.documents[this.documents.length - 1].document =
|
|
@@ -21479,13 +21634,17 @@ class BundleLoader {
|
|
|
21479
21634
|
* Update the progress to 'Success' and return the updated progress.
|
|
21480
21635
|
*/
|
|
21481
21636
|
async complete() {
|
|
21482
|
-
const
|
|
21637
|
+
const changedDocs = await localStoreApplyBundledDocuments(this.localStore, new BundleConverterImpl(this.serializer), this.documents, this.bundleMetadata.id);
|
|
21483
21638
|
const queryDocumentMap = this.getQueryDocumentMapping(this.documents);
|
|
21484
21639
|
for (const q of this.queries) {
|
|
21485
21640
|
await localStoreSaveNamedQuery(this.localStore, q, queryDocumentMap.get(q.name));
|
|
21486
21641
|
}
|
|
21487
21642
|
this.progress.taskState = 'Success';
|
|
21488
|
-
return
|
|
21643
|
+
return {
|
|
21644
|
+
progress: this.progress,
|
|
21645
|
+
changedCollectionGroups: this.collectionGroups,
|
|
21646
|
+
changedDocs
|
|
21647
|
+
};
|
|
21489
21648
|
}
|
|
21490
21649
|
}
|
|
21491
21650
|
/**
|
|
@@ -22564,9 +22723,9 @@ async function synchronizeViewAndComputeSnapshot(syncEngine, queryView) {
|
|
|
22564
22723
|
* snapshots if needed.
|
|
22565
22724
|
*/
|
|
22566
22725
|
// PORTING NOTE: Multi-Tab only.
|
|
22567
|
-
async function syncEngineSynchronizeWithChangedDocuments(syncEngine) {
|
|
22726
|
+
async function syncEngineSynchronizeWithChangedDocuments(syncEngine, collectionGroup) {
|
|
22568
22727
|
const syncEngineImpl = debugCast(syncEngine);
|
|
22569
|
-
return localStoreGetNewDocumentChanges(syncEngineImpl.localStore).then(changes => syncEngineEmitNewSnapsAndNotifyLocalStore(syncEngineImpl, changes));
|
|
22728
|
+
return localStoreGetNewDocumentChanges(syncEngineImpl.localStore, collectionGroup).then(changes => syncEngineEmitNewSnapsAndNotifyLocalStore(syncEngineImpl, changes));
|
|
22570
22729
|
}
|
|
22571
22730
|
/** Applies a mutation state to an existing batch. */
|
|
22572
22731
|
// PORTING NOTE: Multi-Tab only.
|
|
@@ -22731,11 +22890,12 @@ async function syncEngineApplyTargetState(syncEngine, targetId, state, error) {
|
|
|
22731
22890
|
logDebug(LOG_TAG$3, 'Ignoring unexpected query state notification.');
|
|
22732
22891
|
return;
|
|
22733
22892
|
}
|
|
22734
|
-
|
|
22893
|
+
const query = syncEngineImpl.queriesByTarget.get(targetId);
|
|
22894
|
+
if (query && query.length > 0) {
|
|
22735
22895
|
switch (state) {
|
|
22736
22896
|
case 'current':
|
|
22737
22897
|
case 'not-current': {
|
|
22738
|
-
const changes = await localStoreGetNewDocumentChanges(syncEngineImpl.localStore);
|
|
22898
|
+
const changes = await localStoreGetNewDocumentChanges(syncEngineImpl.localStore, queryCollectionGroup(query[0]));
|
|
22739
22899
|
const synthesizedRemoteEvent = RemoteEvent.createSynthesizedRemoteEventForCurrentChange(targetId, state === 'current');
|
|
22740
22900
|
await syncEngineEmitNewSnapsAndNotifyLocalStore(syncEngineImpl, changes, synthesizedRemoteEvent);
|
|
22741
22901
|
break;
|
|
@@ -22818,10 +22978,11 @@ function syncEngineEnsureWriteCallbacks(syncEngine) {
|
|
|
22818
22978
|
function syncEngineLoadBundle(syncEngine, bundleReader, task) {
|
|
22819
22979
|
const syncEngineImpl = debugCast(syncEngine);
|
|
22820
22980
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
22821
|
-
loadBundleImpl(syncEngineImpl, bundleReader, task).then(
|
|
22822
|
-
syncEngineImpl.sharedClientState.notifyBundleLoaded();
|
|
22981
|
+
loadBundleImpl(syncEngineImpl, bundleReader, task).then(collectionGroups => {
|
|
22982
|
+
syncEngineImpl.sharedClientState.notifyBundleLoaded(collectionGroups);
|
|
22823
22983
|
});
|
|
22824
22984
|
}
|
|
22985
|
+
/** Loads a bundle and returns the list of affected collection groups. */
|
|
22825
22986
|
async function loadBundleImpl(syncEngine, reader, task) {
|
|
22826
22987
|
try {
|
|
22827
22988
|
const metadata = await reader.getMetadata();
|
|
@@ -22829,7 +22990,7 @@ async function loadBundleImpl(syncEngine, reader, task) {
|
|
|
22829
22990
|
if (skip) {
|
|
22830
22991
|
await reader.close();
|
|
22831
22992
|
task._completeWith(bundleSuccessProgress(metadata));
|
|
22832
|
-
return;
|
|
22993
|
+
return Promise.resolve(new Set());
|
|
22833
22994
|
}
|
|
22834
22995
|
task._updateProgress(bundleInitialProgress(metadata));
|
|
22835
22996
|
const loader = new BundleLoader(metadata, syncEngine.localStore, reader.serializer);
|
|
@@ -22843,18 +23004,17 @@ async function loadBundleImpl(syncEngine, reader, task) {
|
|
|
22843
23004
|
element = await reader.nextElement();
|
|
22844
23005
|
}
|
|
22845
23006
|
const result = await loader.complete();
|
|
22846
|
-
// TODO(b/160876443): This currently raises snapshots with
|
|
22847
|
-
// `fromCache=false` if users already listen to some queries and bundles
|
|
22848
|
-
// has newer version.
|
|
22849
23007
|
await syncEngineEmitNewSnapsAndNotifyLocalStore(syncEngine, result.changedDocs,
|
|
22850
23008
|
/* remoteEvent */ undefined);
|
|
22851
23009
|
// Save metadata, so loading the same bundle will skip.
|
|
22852
23010
|
await localStoreSaveBundle(syncEngine.localStore, metadata);
|
|
22853
23011
|
task._completeWith(result.progress);
|
|
23012
|
+
return Promise.resolve(result.changedCollectionGroups);
|
|
22854
23013
|
}
|
|
22855
23014
|
catch (e) {
|
|
22856
23015
|
logWarn(LOG_TAG$3, `Loading bundle failed with ${e}`);
|
|
22857
23016
|
task._failWith(e);
|
|
23017
|
+
return Promise.resolve(new Set());
|
|
22858
23018
|
}
|
|
22859
23019
|
}
|
|
22860
23020
|
|
|
@@ -22923,7 +23083,6 @@ class IndexedDbOfflineComponentProvider extends MemoryOfflineComponentProvider {
|
|
|
22923
23083
|
}
|
|
22924
23084
|
async initialize(cfg) {
|
|
22925
23085
|
await super.initialize(cfg);
|
|
22926
|
-
await localStoreSynchronizeLastDocumentChangeReadTime(this.localStore);
|
|
22927
23086
|
await this.onlineComponentProvider.initialize(this, cfg);
|
|
22928
23087
|
// Enqueue writes from a previous session
|
|
22929
23088
|
await syncEngineEnsureWriteCallbacks(this.onlineComponentProvider.syncEngine);
|