@powersync/service-module-mongodb-storage 0.0.0-dev-20260602073133 → 0.0.0-dev-20260909133214
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 +177 -5
- package/dist/migrations/db/migrations/1782950400000-checkpoint-requested-at-index.d.ts +3 -0
- package/dist/migrations/db/migrations/1782950400000-checkpoint-requested-at-index.js +41 -0
- package/dist/migrations/db/migrations/1782950400000-checkpoint-requested-at-index.js.map +1 -0
- package/dist/storage/MongoBucketStorage.d.ts +71 -18
- package/dist/storage/MongoBucketStorage.js +516 -202
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoBucketBatch.d.ts +71 -29
- package/dist/storage/implementation/MongoBucketBatch.js +140 -66
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoChecksums.d.ts +41 -13
- package/dist/storage/implementation/MongoChecksums.js +36 -121
- package/dist/storage/implementation/MongoChecksums.js.map +1 -1
- package/dist/storage/implementation/MongoCompactor.d.ts +28 -90
- package/dist/storage/implementation/MongoCompactor.js +87 -481
- package/dist/storage/implementation/MongoCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoHydrationState.d.ts +11 -0
- package/dist/storage/implementation/MongoHydrationState.js +49 -0
- package/dist/storage/implementation/MongoHydrationState.js.map +1 -0
- package/dist/storage/implementation/MongoParameterCompactor.d.ts +82 -8
- package/dist/storage/implementation/MongoParameterCompactor.js +312 -76
- package/dist/storage/implementation/MongoParameterCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoParsedSyncConfigSet.d.ts +21 -0
- package/dist/storage/implementation/MongoParsedSyncConfigSet.js +93 -0
- package/dist/storage/implementation/MongoParsedSyncConfigSet.js.map +1 -0
- package/dist/storage/implementation/MongoPersistedReplicationStream.d.ts +36 -0
- package/dist/storage/implementation/MongoPersistedReplicationStream.js +90 -0
- package/dist/storage/implementation/MongoPersistedReplicationStream.js.map +1 -0
- package/dist/storage/implementation/MongoPersistedSyncConfigContent.d.ts +25 -0
- package/dist/storage/implementation/MongoPersistedSyncConfigContent.js +125 -0
- package/dist/storage/implementation/MongoPersistedSyncConfigContent.js.map +1 -0
- package/dist/storage/implementation/MongoStorageProvider.js +41 -4
- package/dist/storage/implementation/MongoStorageProvider.js.map +1 -1
- package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +81 -37
- package/dist/storage/implementation/MongoSyncBucketStorage.js +159 -86
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.d.ts +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.js +23 -11
- package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/implementation/MongoWriteCheckpointAPI.d.ts +11 -8
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js +159 -33
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
- package/dist/storage/implementation/SyncRuleStateUpdate.d.ts +11 -5
- package/dist/storage/implementation/SyncRuleStateUpdate.js +14 -6
- package/dist/storage/implementation/SyncRuleStateUpdate.js.map +1 -1
- package/dist/storage/implementation/common/MongoSyncBucketStorageCheckpoint.d.ts +28 -0
- package/dist/storage/implementation/common/MongoSyncBucketStorageCheckpoint.js +2 -0
- package/dist/storage/implementation/common/MongoSyncBucketStorageCheckpoint.js.map +1 -0
- package/dist/storage/implementation/common/PersistedBatch.d.ts +34 -2
- package/dist/storage/implementation/common/PersistedBatch.js +63 -10
- package/dist/storage/implementation/common/PersistedBatch.js.map +1 -1
- package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.js +1 -1
- package/dist/storage/implementation/common/VersionedPowerSyncMongoBase.js.map +1 -1
- package/dist/storage/implementation/createMongoSyncBucketStorage.d.ts +2 -2
- package/dist/storage/implementation/createMongoSyncBucketStorage.js +4 -4
- package/dist/storage/implementation/createMongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/db.d.ts +4 -1
- package/dist/storage/implementation/db.js +31 -16
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/models.d.ts +55 -13
- package/dist/storage/implementation/models.js.map +1 -1
- package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +15 -1
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js +135 -107
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js.map +1 -1
- package/dist/storage/implementation/v1/MongoChecksumsV1.d.ts +4 -4
- package/dist/storage/implementation/v1/MongoChecksumsV1.js +119 -7
- package/dist/storage/implementation/v1/MongoChecksumsV1.js.map +1 -1
- package/dist/storage/implementation/v1/MongoCompactorV1.d.ts +47 -7
- package/dist/storage/implementation/v1/MongoCompactorV1.js +478 -8
- package/dist/storage/implementation/v1/MongoCompactorV1.js.map +1 -1
- package/dist/storage/implementation/v1/MongoParameterCompactorV1.d.ts +16 -2
- package/dist/storage/implementation/v1/MongoParameterCompactorV1.js +20 -9
- package/dist/storage/implementation/v1/MongoParameterCompactorV1.js.map +1 -1
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.d.ts +33 -27
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +146 -73
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js.map +1 -1
- package/dist/storage/implementation/v1/SingleBucketStoreV1.d.ts +9 -10
- package/dist/storage/implementation/v1/SingleBucketStoreV1.js +2 -8
- package/dist/storage/implementation/v1/SingleBucketStoreV1.js.map +1 -1
- package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.d.ts +2 -1
- package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.js +3 -0
- package/dist/storage/implementation/v1/VersionedPowerSyncMongoV1.js.map +1 -1
- package/dist/storage/implementation/v1/models.d.ts +10 -1
- package/dist/storage/implementation/v1/models.js +1 -0
- package/dist/storage/implementation/v1/models.js.map +1 -1
- package/dist/storage/implementation/v3/BucketDataContextV3.d.ts +13 -0
- package/dist/storage/implementation/v3/BucketDataContextV3.js +23 -0
- package/dist/storage/implementation/v3/BucketDataContextV3.js.map +1 -0
- package/dist/storage/implementation/v3/CompactionLease.d.ts +50 -0
- package/dist/storage/implementation/v3/CompactionLease.js +131 -0
- package/dist/storage/implementation/v3/CompactionLease.js.map +1 -0
- package/dist/storage/implementation/v3/MongoBucketBatchV3.d.ts +16 -5
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js +393 -262
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoChecksumsV3.d.ts +30 -9
- package/dist/storage/implementation/v3/MongoChecksumsV3.js +161 -20
- package/dist/storage/implementation/v3/MongoChecksumsV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoCompactorV3.d.ts +108 -18
- package/dist/storage/implementation/v3/MongoCompactorV3.js +1115 -47
- package/dist/storage/implementation/v3/MongoCompactorV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.d.ts +12 -3
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.js +13 -8
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoStoppedSyncConfigCleanup.d.ts +54 -0
- package/dist/storage/implementation/v3/MongoStoppedSyncConfigCleanup.js +319 -0
- package/dist/storage/implementation/v3/MongoStoppedSyncConfigCleanup.js.map +1 -0
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.d.ts +61 -36
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +353 -161
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoWriteCheckpointAPIV3.d.ts +26 -0
- package/dist/storage/implementation/v3/MongoWriteCheckpointAPIV3.js +82 -0
- package/dist/storage/implementation/v3/MongoWriteCheckpointAPIV3.js.map +1 -0
- package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +8 -3
- package/dist/storage/implementation/v3/PersistedBatchV3.js +131 -29
- package/dist/storage/implementation/v3/PersistedBatchV3.js.map +1 -1
- package/dist/storage/implementation/v3/SourceRecordStoreV3.d.ts +3 -3
- package/dist/storage/implementation/v3/SourceRecordStoreV3.js +13 -11
- package/dist/storage/implementation/v3/SourceRecordStoreV3.js.map +1 -1
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.d.ts +26 -14
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js +73 -29
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js.map +1 -1
- package/dist/storage/implementation/v3/bucket-format.d.ts +13 -0
- package/dist/storage/implementation/v3/bucket-format.js +79 -0
- package/dist/storage/implementation/v3/bucket-format.js.map +1 -0
- package/dist/storage/implementation/v3/chunking.d.ts +10 -0
- package/dist/storage/implementation/v3/chunking.js +30 -0
- package/dist/storage/implementation/v3/chunking.js.map +1 -0
- package/dist/storage/implementation/v3/compact-utils.d.ts +107 -0
- package/dist/storage/implementation/v3/compact-utils.js +216 -0
- package/dist/storage/implementation/v3/compact-utils.js.map +1 -0
- package/dist/storage/implementation/v3/compaction-constants.d.ts +5 -0
- package/dist/storage/implementation/v3/compaction-constants.js +6 -0
- package/dist/storage/implementation/v3/compaction-constants.js.map +1 -0
- package/dist/storage/implementation/v3/models.d.ts +187 -23
- package/dist/storage/implementation/v3/models.js +11 -28
- package/dist/storage/implementation/v3/models.js.map +1 -1
- package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.d.ts +20 -0
- package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.js +48 -0
- package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.js.map +1 -0
- package/dist/storage/implementation/v3/object-storage/ObjectStorage.d.ts +33 -0
- package/dist/storage/implementation/v3/object-storage/ObjectStorage.js +12 -0
- package/dist/storage/implementation/v3/object-storage/ObjectStorage.js.map +1 -0
- package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.d.ts +68 -0
- package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.js +154 -0
- package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.js.map +1 -0
- package/dist/storage/implementation/v3/object-storage/ObjectStorageUsage.d.ts +37 -0
- package/dist/storage/implementation/v3/object-storage/ObjectStorageUsage.js +167 -0
- package/dist/storage/implementation/v3/object-storage/ObjectStorageUsage.js.map +1 -0
- package/dist/storage/implementation/v3/object-storage/S3ObjectStorage.d.ts +67 -0
- package/dist/storage/implementation/v3/object-storage/S3ObjectStorage.js +439 -0
- package/dist/storage/implementation/v3/object-storage/S3ObjectStorage.js.map +1 -0
- package/dist/storage/implementation/v3/source-table-utils.d.ts +63 -0
- package/dist/storage/implementation/v3/source-table-utils.js +206 -0
- package/dist/storage/implementation/v3/source-table-utils.js.map +1 -0
- package/dist/storage/storage-index.d.ts +5 -4
- package/dist/storage/storage-index.js +5 -4
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/types/types.d.ts +71 -3
- package/dist/types/types.js +58 -2
- package/dist/types/types.js.map +1 -1
- package/dist/utils/test-utils.d.ts +1 -2
- package/dist/utils/test-utils.js +7 -1
- package/dist/utils/test-utils.js.map +1 -1
- package/dist/utils/util.d.ts +9 -2
- package/dist/utils/util.js +131 -5
- package/dist/utils/util.js.map +1 -1
- package/package.json +13 -19
- package/src/migrations/db/migrations/1782950400000-checkpoint-requested-at-index.ts +55 -0
- package/src/storage/MongoBucketStorage.ts +728 -242
- package/src/storage/implementation/MongoBucketBatch.ts +196 -91
- package/src/storage/implementation/MongoChecksums.ts +93 -153
- package/src/storage/implementation/MongoCompactor.ts +106 -631
- package/src/storage/implementation/MongoHydrationState.ts +61 -0
- package/src/storage/implementation/MongoParameterCompactor.ts +392 -87
- package/src/storage/implementation/MongoParsedSyncConfigSet.ts +122 -0
- package/src/storage/implementation/MongoPersistedReplicationStream.ts +118 -0
- package/src/storage/implementation/MongoPersistedSyncConfigContent.ts +156 -0
- package/src/storage/implementation/MongoStorageProvider.ts +48 -4
- package/src/storage/implementation/MongoSyncBucketStorage.ts +226 -118
- package/src/storage/implementation/MongoSyncRulesLock.ts +28 -12
- package/src/storage/implementation/MongoWriteCheckpointAPI.ts +194 -52
- package/src/storage/implementation/SyncRuleStateUpdate.ts +13 -6
- package/src/storage/implementation/common/MongoSyncBucketStorageCheckpoint.ts +31 -0
- package/src/storage/implementation/common/PersistedBatch.ts +83 -15
- package/src/storage/implementation/common/VersionedPowerSyncMongoBase.ts +1 -1
- package/src/storage/implementation/createMongoSyncBucketStorage.ts +21 -7
- package/src/storage/implementation/db.ts +40 -22
- package/src/storage/implementation/models.ts +58 -14
- package/src/storage/implementation/v1/MongoBucketBatchV1.ts +174 -125
- package/src/storage/implementation/v1/MongoChecksumsV1.ts +154 -12
- package/src/storage/implementation/v1/MongoCompactorV1.ts +594 -25
- package/src/storage/implementation/v1/MongoParameterCompactorV1.ts +25 -9
- package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +226 -129
- package/src/storage/implementation/v1/SingleBucketStoreV1.ts +18 -27
- package/src/storage/implementation/v1/VersionedPowerSyncMongoV1.ts +11 -1
- package/src/storage/implementation/v1/models.ts +12 -1
- package/src/storage/implementation/v3/BucketDataContextV3.ts +32 -0
- package/src/storage/implementation/v3/CompactionLease.ts +152 -0
- package/src/storage/implementation/v3/MongoBucketBatchV3.ts +502 -324
- package/src/storage/implementation/v3/MongoChecksumsV3.ts +250 -32
- package/src/storage/implementation/v3/MongoCompactorV3.ts +1439 -70
- package/src/storage/implementation/v3/MongoParameterCompactorV3.ts +19 -9
- package/src/storage/implementation/v3/MongoStoppedSyncConfigCleanup.ts +473 -0
- package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +453 -211
- package/src/storage/implementation/v3/MongoWriteCheckpointAPIV3.ts +111 -0
- package/src/storage/implementation/v3/PersistedBatchV3.ts +169 -45
- package/src/storage/implementation/v3/SourceRecordStoreV3.ts +12 -12
- package/src/storage/implementation/v3/VersionedPowerSyncMongoV3.ts +99 -38
- package/src/storage/implementation/v3/bucket-format.ts +99 -0
- package/src/storage/implementation/v3/chunking.ts +40 -0
- package/src/storage/implementation/v3/compact-utils.ts +320 -0
- package/src/storage/implementation/v3/compaction-constants.ts +5 -0
- package/src/storage/implementation/v3/models.ts +228 -58
- package/src/storage/implementation/v3/object-storage/BucketDataObjectStorage.ts +62 -0
- package/src/storage/implementation/v3/object-storage/ObjectStorage.ts +44 -0
- package/src/storage/implementation/v3/object-storage/ObjectStorageLifecycle.ts +182 -0
- package/src/storage/implementation/v3/object-storage/ObjectStorageUsage.ts +230 -0
- package/src/storage/implementation/v3/object-storage/S3ObjectStorage.ts +573 -0
- package/src/storage/implementation/v3/source-table-utils.ts +398 -0
- package/src/storage/storage-index.ts +14 -4
- package/src/types/types.ts +76 -2
- package/src/utils/test-utils.ts +8 -3
- package/src/utils/util.ts +188 -7
- package/test/src/__snapshots__/storage.test.ts.snap +4 -54
- package/test/src/__snapshots__/storage_sync.test.ts.snap +652 -645
- package/test/src/cleanup-stopped-sync-configs.test.ts +698 -0
- package/test/src/compact-utils.test.ts +226 -0
- package/test/src/helpers/MemoryObjectStorage.ts +61 -0
- package/test/src/helpers/s3TestFactory.ts +69 -0
- package/test/src/object_storage_lifecycle.test.ts +59 -0
- package/test/src/object_storage_usage.test.ts +255 -0
- package/test/src/parameter_compacting_v1.test.ts +120 -0
- package/test/src/parameter_compacting_v3.test.ts +192 -0
- package/test/src/parameter_compaction_fence.test.ts +276 -0
- package/test/src/setup.ts +6 -1
- package/test/src/storage.test.ts +478 -13
- package/test/src/storage_compacting.test.ts +2516 -107
- package/test/src/storage_object_storage_inline_threshold.test.ts +116 -0
- package/test/src/storage_s3_checksums.test.ts +190 -0
- package/test/src/storage_s3_compaction_lifecycle.test.ts +543 -0
- package/test/src/storage_s3_reading.test.ts +768 -0
- package/test/src/storage_s3_writing.test.ts +136 -0
- package/test/src/storage_sync.test.ts +1507 -76
- package/test/src/storeCurrentData.test.ts +227 -0
- package/test/src/util.ts +3 -2
- package/tsconfig.json +1 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/storage/implementation/BucketDefinitionMapping.d.ts +0 -15
- package/dist/storage/implementation/BucketDefinitionMapping.js +0 -58
- package/dist/storage/implementation/BucketDefinitionMapping.js.map +0 -1
- package/dist/storage/implementation/MongoPersistedSyncRules.d.ts +0 -14
- package/dist/storage/implementation/MongoPersistedSyncRules.js +0 -67
- package/dist/storage/implementation/MongoPersistedSyncRules.js.map +0 -1
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.d.ts +0 -29
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js +0 -76
- package/dist/storage/implementation/MongoPersistedSyncRulesContent.js.map +0 -1
- package/dist/storage/implementation/common/MongoSyncBucketStorageContext.d.ts +0 -13
- package/dist/storage/implementation/common/MongoSyncBucketStorageContext.js +0 -2
- package/dist/storage/implementation/common/MongoSyncBucketStorageContext.js.map +0 -1
- package/dist/storage/implementation/common/SingleBucketStore.d.ts +0 -54
- package/dist/storage/implementation/common/SingleBucketStore.js +0 -3
- package/dist/storage/implementation/common/SingleBucketStore.js.map +0 -1
- package/dist/storage/implementation/v3/MongoParameterLookupV3.d.ts +0 -4
- package/dist/storage/implementation/v3/MongoParameterLookupV3.js +0 -9
- package/dist/storage/implementation/v3/MongoParameterLookupV3.js.map +0 -1
- package/dist/storage/implementation/v3/SingleBucketStoreV3.d.ts +0 -18
- package/dist/storage/implementation/v3/SingleBucketStoreV3.js +0 -48
- package/dist/storage/implementation/v3/SingleBucketStoreV3.js.map +0 -1
- package/src/storage/implementation/BucketDefinitionMapping.ts +0 -75
- package/src/storage/implementation/MongoPersistedSyncRules.ts +0 -82
- package/src/storage/implementation/MongoPersistedSyncRulesContent.ts +0 -101
- package/src/storage/implementation/common/MongoSyncBucketStorageContext.ts +0 -15
- package/src/storage/implementation/common/SingleBucketStore.ts +0 -63
- package/src/storage/implementation/v3/MongoParameterLookupV3.ts +0 -11
- package/src/storage/implementation/v3/SingleBucketStoreV3.ts +0 -68
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
|
+
import { bson, InternalOpId } from '@powersync/service-core';
|
|
2
3
|
import { MongoParameterCompactor } from '../MongoParameterCompactor.js';
|
|
3
4
|
import { VersionedPowerSyncMongoV1 } from './VersionedPowerSyncMongoV1.js';
|
|
4
5
|
|
|
@@ -9,18 +10,33 @@ export class MongoParameterCompactorV1 extends MongoParameterCompactor {
|
|
|
9
10
|
return [this.db.parameterIndexV1 as unknown as mongo.Collection<mongo.Document>];
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
// The shared V1 collection is scanned using only its default `_id` index. Filter the stream in
|
|
14
|
+
// code so compaction does not require an index on `key.g`.
|
|
15
|
+
protected override shouldCompactDocument(doc: { key: mongo.Document }): boolean {
|
|
16
|
+
return doc.key.g === this.replicationStreamId;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Uses the legacy `{ 'key.g': 1, lookup: 1, _id: 1 }` index to narrow the stream, lookup and
|
|
21
|
+
* operation-id range. `key` is not part of that index at all, so it is a residual predicate applied
|
|
22
|
+
* to every document the range scan returns.
|
|
23
|
+
*
|
|
24
|
+
* That scan may therefore have to filter through many keys for the same lookup, but the cost is
|
|
25
|
+
* amortized: a single scan covers up to 1000 keys, and identities seen again in a later batch skip
|
|
26
|
+
* the scan entirely - they are deleted by `_id`.
|
|
27
|
+
*
|
|
28
|
+
* The V3 storage format uses an index more suitable for this.
|
|
29
|
+
*/
|
|
30
|
+
protected leadingHistoryDeleteFilter(
|
|
31
|
+
lookup: bson.Binary,
|
|
32
|
+
keys: mongo.Document[],
|
|
33
|
+
before: InternalOpId
|
|
34
|
+
): mongo.Document {
|
|
19
35
|
return {
|
|
20
|
-
'key.g':
|
|
21
|
-
lookup
|
|
22
|
-
|
|
23
|
-
|
|
36
|
+
'key.g': this.replicationStreamId,
|
|
37
|
+
lookup,
|
|
38
|
+
key: { $in: keys },
|
|
39
|
+
_id: { $lt: before }
|
|
24
40
|
};
|
|
25
41
|
}
|
|
26
42
|
}
|
|
@@ -3,6 +3,8 @@ import { mongo } from '@powersync/lib-service-mongodb';
|
|
|
3
3
|
import { ServiceAssertionError } from '@powersync/lib-services-framework';
|
|
4
4
|
import {
|
|
5
5
|
CheckpointChanges,
|
|
6
|
+
CompactInitialReplicationOptions,
|
|
7
|
+
CompactInitialReplicationResults,
|
|
6
8
|
deserializeParameterLookup,
|
|
7
9
|
GetCheckpointChangesOptions,
|
|
8
10
|
InternalOpId,
|
|
@@ -16,19 +18,30 @@ import {
|
|
|
16
18
|
import { JSONBig } from '@powersync/service-jsonbig';
|
|
17
19
|
import { ParameterLookupRows, ScopedParameterLookup, SqliteJsonRow } from '@powersync/service-sync-rules';
|
|
18
20
|
import * as bson from 'bson';
|
|
19
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
clearCollectionInIdBatches,
|
|
23
|
+
clearCollectionInIdRanges,
|
|
24
|
+
idPrefixFilter,
|
|
25
|
+
mapOpEntry,
|
|
26
|
+
readSingleBatch,
|
|
27
|
+
retryOnMongoMaxTimeMSExpired,
|
|
28
|
+
setSessionSnapshotTime
|
|
29
|
+
} from '../../../utils/util.js';
|
|
20
30
|
import { MongoBucketStorage } from '../../MongoBucketStorage.js';
|
|
21
31
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
} from '../common/
|
|
32
|
+
MongoGetCheckpointChangesOptions,
|
|
33
|
+
MongoSyncBucketStorageCheckpoint
|
|
34
|
+
} from '../common/MongoSyncBucketStorageCheckpoint.js';
|
|
25
35
|
import { SourceKey } from '../models.js';
|
|
26
|
-
import { MongoBucketBatchOptions } from '../MongoBucketBatch.js';
|
|
27
36
|
import { MongoChecksums } from '../MongoChecksums.js';
|
|
28
|
-
import { MongoCompactOptions
|
|
37
|
+
import { MongoCompactOptions } from '../MongoCompactor.js';
|
|
29
38
|
import { MongoParameterCompactor } from '../MongoParameterCompactor.js';
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
39
|
+
import { MongoPersistedReplicationStream } from '../MongoPersistedReplicationStream.js';
|
|
40
|
+
import {
|
|
41
|
+
MongoCheckpointState,
|
|
42
|
+
MongoSyncBucketStorage,
|
|
43
|
+
MongoSyncBucketStorageOptions
|
|
44
|
+
} from '../MongoSyncBucketStorage.js';
|
|
32
45
|
import {
|
|
33
46
|
BucketDataDocumentV1,
|
|
34
47
|
BucketDataKeyV1,
|
|
@@ -42,67 +55,91 @@ import { MongoCompactorV1 } from './MongoCompactorV1.js';
|
|
|
42
55
|
import { MongoParameterCompactorV1 } from './MongoParameterCompactorV1.js';
|
|
43
56
|
import { VersionedPowerSyncMongoV1 } from './VersionedPowerSyncMongoV1.js';
|
|
44
57
|
|
|
58
|
+
export interface MongoSyncBucketStorageContextV1 {
|
|
59
|
+
db: VersionedPowerSyncMongoV1;
|
|
60
|
+
replicationStreamId: number;
|
|
61
|
+
readPreference?: mongo.ReadPreference;
|
|
62
|
+
}
|
|
63
|
+
|
|
45
64
|
export class MongoSyncBucketStorageV1 extends MongoSyncBucketStorage {
|
|
46
|
-
// Declare types to be more specific
|
|
47
65
|
declare readonly db: VersionedPowerSyncMongoV1;
|
|
48
66
|
declare readonly checksums: MongoChecksumsV1;
|
|
49
67
|
|
|
50
68
|
constructor(
|
|
51
69
|
factory: MongoBucketStorage,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
70
|
+
replicationStreamId: number,
|
|
71
|
+
replicationStream: MongoPersistedReplicationStream,
|
|
72
|
+
replicationStreamName: string,
|
|
55
73
|
writeCheckpointMode: storage.WriteCheckpointMode | undefined,
|
|
56
74
|
options: MongoSyncBucketStorageOptions
|
|
57
75
|
) {
|
|
58
|
-
super(factory,
|
|
76
|
+
super(factory, replicationStreamId, replicationStream, replicationStreamName, writeCheckpointMode, options);
|
|
59
77
|
}
|
|
60
78
|
|
|
61
79
|
protected async initializeVersionStorage(): Promise<void> {}
|
|
62
80
|
|
|
63
|
-
protected
|
|
64
|
-
return new MongoBucketBatchV1(batchOptions);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
protected async fetchCheckpointState(
|
|
68
|
-
session: mongo.ClientSession
|
|
69
|
-
): Promise<{ checkpoint: bigint; lsn: string | null } | null> {
|
|
81
|
+
protected async fetchPersistedOpHead(): Promise<InternalOpId | null> {
|
|
70
82
|
const doc = (await this.db.sync_rules.findOne(
|
|
71
|
-
{ _id: this.
|
|
72
|
-
{
|
|
73
|
-
session,
|
|
74
|
-
projection: { _id: 1, state: 1, last_checkpoint: 1, last_checkpoint_lsn: 1, snapshot_done: 1 }
|
|
75
|
-
}
|
|
83
|
+
{ _id: this.replicationStreamId },
|
|
84
|
+
{ projection: { keepalive_op: 1, last_checkpoint: 1 } }
|
|
76
85
|
)) as SyncRuleDocumentV1;
|
|
77
|
-
|
|
86
|
+
// keepalive_op covers ops not yet in a checkpoint (cleared once checkpointed),
|
|
87
|
+
// so the head is the max of the two.
|
|
88
|
+
const keepaliveOp = doc?.keepalive_op == null ? null : BigInt(doc.keepalive_op);
|
|
89
|
+
const lastCheckpoint = doc?.last_checkpoint ?? null;
|
|
90
|
+
if (keepaliveOp == null && lastCheckpoint == null) {
|
|
78
91
|
return null;
|
|
79
92
|
}
|
|
80
|
-
return
|
|
81
|
-
checkpoint: doc.last_checkpoint ?? 0n,
|
|
82
|
-
lsn: doc.last_checkpoint_lsn ?? null
|
|
83
|
-
};
|
|
93
|
+
return (keepaliveOp ?? 0n) > (lastCheckpoint ?? 0n) ? keepaliveOp : lastCheckpoint;
|
|
84
94
|
}
|
|
85
95
|
|
|
86
|
-
protected async
|
|
96
|
+
protected async createWriterImpl(options: storage.CreateWriterOptions): Promise<storage.BucketStorageBatch> {
|
|
87
97
|
const doc = (await this.db.sync_rules.findOne(
|
|
88
98
|
{
|
|
89
|
-
_id: this.
|
|
99
|
+
_id: this.replicationStreamId
|
|
90
100
|
},
|
|
91
101
|
{ projection: { last_checkpoint_lsn: 1, keepalive_op: 1, snapshot_lsn: 1 } }
|
|
92
102
|
)) as SyncRuleDocumentV1;
|
|
93
|
-
|
|
103
|
+
|
|
104
|
+
return new MongoBucketBatchV1({
|
|
105
|
+
...this.writerBatchOptions(options),
|
|
106
|
+
// Resume from the last consistent checkpoint, or the in-progress snapshot position if it is newer.
|
|
107
|
+
resumeFromLsn: maxLsn(doc?.last_checkpoint_lsn, doc?.snapshot_lsn),
|
|
108
|
+
keepaliveOp: doc?.keepalive_op ? BigInt(doc.keepalive_op) : null
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
protected async fetchCheckpointState(session: mongo.ClientSession): Promise<MongoCheckpointState | null> {
|
|
113
|
+
const doc = (await this.db.sync_rules.findOne(
|
|
114
|
+
{ _id: this.replicationStreamId },
|
|
115
|
+
{
|
|
116
|
+
session,
|
|
117
|
+
projection: {
|
|
118
|
+
_id: 1,
|
|
119
|
+
state: 1,
|
|
120
|
+
last_checkpoint: 1,
|
|
121
|
+
last_checkpoint_lsn: 1,
|
|
122
|
+
snapshot_done: 1,
|
|
123
|
+
// Must be read in the same snapshot as the checkpoint.
|
|
124
|
+
'parameter_compaction.checkpoint_changes_invalid_before': 1
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
)) as SyncRuleDocumentV1;
|
|
128
|
+
if (!doc?.snapshot_done || ![storage.SyncRuleState.ACTIVE, storage.SyncRuleState.ERRORED].includes(doc.state)) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
94
131
|
return {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
132
|
+
checkpoint: doc.last_checkpoint ?? 0n,
|
|
133
|
+
lsn: doc.last_checkpoint_lsn ?? null,
|
|
134
|
+
// Defaults to 0n for streams that have never been compacted.
|
|
135
|
+
parameterChangesInvalidBefore: doc.parameter_compaction?.checkpoint_changes_invalid_before ?? 0n
|
|
99
136
|
};
|
|
100
137
|
}
|
|
101
138
|
|
|
102
139
|
protected async terminateSyncRuleState(): Promise<void> {
|
|
103
140
|
await this.db.sync_rules.updateOne(
|
|
104
141
|
{
|
|
105
|
-
_id: this.
|
|
142
|
+
_id: this.replicationStreamId
|
|
106
143
|
},
|
|
107
144
|
{
|
|
108
145
|
$set: {
|
|
@@ -114,18 +151,16 @@ export class MongoSyncBucketStorageV1 extends MongoSyncBucketStorage {
|
|
|
114
151
|
);
|
|
115
152
|
}
|
|
116
153
|
|
|
117
|
-
protected async getStatusImpl(): Promise<storage.
|
|
154
|
+
protected async getStatusImpl(): Promise<storage.ReplicationStreamStatus> {
|
|
118
155
|
const doc = (await this.db.sync_rules.findOne(
|
|
119
156
|
{
|
|
120
|
-
_id: this.
|
|
157
|
+
_id: this.replicationStreamId
|
|
121
158
|
},
|
|
122
159
|
{
|
|
123
160
|
projection: {
|
|
124
161
|
snapshot_done: 1,
|
|
125
162
|
last_checkpoint_lsn: 1,
|
|
126
|
-
|
|
127
|
-
snapshot_lsn: 1,
|
|
128
|
-
keepalive_op: 1
|
|
163
|
+
snapshot_lsn: 1
|
|
129
164
|
}
|
|
130
165
|
}
|
|
131
166
|
)) as SyncRuleDocumentV1;
|
|
@@ -134,18 +169,15 @@ export class MongoSyncBucketStorageV1 extends MongoSyncBucketStorage {
|
|
|
134
169
|
}
|
|
135
170
|
|
|
136
171
|
return {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
active: doc.state == storage.SyncRuleState.ACTIVE,
|
|
140
|
-
checkpoint_lsn: doc.last_checkpoint_lsn,
|
|
141
|
-
keepalive_op: doc.keepalive_op == null ? null : BigInt(doc.keepalive_op)
|
|
172
|
+
snapshotDone: doc.snapshot_done && doc.last_checkpoint_lsn != null,
|
|
173
|
+
resumeLsn: maxLsn(doc.snapshot_lsn, doc.last_checkpoint_lsn)
|
|
142
174
|
};
|
|
143
175
|
}
|
|
144
176
|
|
|
145
177
|
protected async clearSyncRuleState(): Promise<void> {
|
|
146
178
|
await this.db.sync_rules.updateOne(
|
|
147
179
|
{
|
|
148
|
-
_id: this.
|
|
180
|
+
_id: this.replicationStreamId
|
|
149
181
|
},
|
|
150
182
|
{
|
|
151
183
|
$set: {
|
|
@@ -156,7 +188,8 @@ export class MongoSyncBucketStorageV1 extends MongoSyncBucketStorage {
|
|
|
156
188
|
no_checkpoint_before: null
|
|
157
189
|
},
|
|
158
190
|
$unset: {
|
|
159
|
-
snapshot_lsn: 1
|
|
191
|
+
snapshot_lsn: 1,
|
|
192
|
+
parameter_compaction: 1
|
|
160
193
|
}
|
|
161
194
|
},
|
|
162
195
|
{ maxTimeMS: lib_mongo.db.MONGO_CLEAR_OPERATION_TIMEOUT_MS }
|
|
@@ -164,29 +197,50 @@ export class MongoSyncBucketStorageV1 extends MongoSyncBucketStorage {
|
|
|
164
197
|
}
|
|
165
198
|
|
|
166
199
|
protected createMongoChecksums(options: MongoSyncBucketStorageOptions): MongoChecksums {
|
|
167
|
-
return new MongoChecksumsV1(this.db, this.
|
|
200
|
+
return new MongoChecksumsV1(this.db, this.replicationStreamId, {
|
|
168
201
|
...options.checksumOptions,
|
|
169
|
-
|
|
170
|
-
|
|
202
|
+
checksumCacheTtlMs: options.checksumCacheTtlMs,
|
|
203
|
+
storageConfig: options?.storageConfig
|
|
171
204
|
});
|
|
172
205
|
}
|
|
173
206
|
|
|
174
|
-
createMongoCompactor(options: MongoCompactOptions):
|
|
207
|
+
createMongoCompactor(options: MongoCompactOptions): MongoCompactorV1 {
|
|
175
208
|
return new MongoCompactorV1(this, this.db, options);
|
|
176
209
|
}
|
|
177
210
|
|
|
211
|
+
async compactInitialReplication(
|
|
212
|
+
options: CompactInitialReplicationOptions
|
|
213
|
+
): Promise<CompactInitialReplicationResults> {
|
|
214
|
+
this.logger.info(`Compacting after initial replication...`);
|
|
215
|
+
const start = Date.now();
|
|
216
|
+
const maxOpId = options.maxOpId ?? (await this.fetchPersistedOpHead()) ?? undefined;
|
|
217
|
+
const compactor = this.createMongoCompactor({
|
|
218
|
+
...options,
|
|
219
|
+
maxOpId,
|
|
220
|
+
memoryLimitMB: 0,
|
|
221
|
+
logger: this.logger
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const result = await compactor.populateChecksums({
|
|
225
|
+
minBucketChanges: options.minBucketChanges ?? 10
|
|
226
|
+
});
|
|
227
|
+
const duration = Date.now() - start;
|
|
228
|
+
this.logger.info(`Compacted after initial replication in ${(duration / 1000).toFixed(1)}s`);
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
231
|
+
|
|
178
232
|
protected createMongoParameterCompactor(
|
|
179
233
|
checkpoint: InternalOpId,
|
|
180
234
|
options: storage.CompactOptions
|
|
181
235
|
): MongoParameterCompactor {
|
|
182
|
-
return new MongoParameterCompactorV1(this.db, this.
|
|
236
|
+
return new MongoParameterCompactorV1(this.db, this.replicationStreamId, checkpoint, options);
|
|
183
237
|
}
|
|
184
238
|
|
|
185
|
-
protected
|
|
239
|
+
protected get versionContext(): MongoSyncBucketStorageContextV1 {
|
|
186
240
|
return {
|
|
187
241
|
db: this.db,
|
|
188
|
-
|
|
189
|
-
|
|
242
|
+
replicationStreamId: this.replicationStreamId,
|
|
243
|
+
readPreference: this.readPreference
|
|
190
244
|
};
|
|
191
245
|
}
|
|
192
246
|
|
|
@@ -199,7 +253,7 @@ export class MongoSyncBucketStorageV1 extends MongoSyncBucketStorage {
|
|
|
199
253
|
}
|
|
200
254
|
|
|
201
255
|
protected getBucketDataBatchImpl(
|
|
202
|
-
checkpoint:
|
|
256
|
+
checkpoint: MongoSyncBucketStorageCheckpoint,
|
|
203
257
|
dataBuckets: storage.BucketDataRequest[],
|
|
204
258
|
options?: storage.BucketDataBatchOptions
|
|
205
259
|
): AsyncIterable<storage.SyncBucketDataChunk> {
|
|
@@ -207,72 +261,77 @@ export class MongoSyncBucketStorageV1 extends MongoSyncBucketStorage {
|
|
|
207
261
|
}
|
|
208
262
|
|
|
209
263
|
protected async clearBucketData(signal?: AbortSignal): Promise<void> {
|
|
210
|
-
await
|
|
264
|
+
await clearCollectionInIdRanges(
|
|
265
|
+
this.logger,
|
|
211
266
|
'bucket data',
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
),
|
|
219
|
-
signal
|
|
267
|
+
this.db.bucket_data,
|
|
268
|
+
{
|
|
269
|
+
_id: idPrefixFilter<BucketDataKeyV1>({ g: this.replicationStreamId }, ['b', 'o'])
|
|
270
|
+
},
|
|
271
|
+
signal,
|
|
272
|
+
this.clearBatchThrottleRate
|
|
220
273
|
);
|
|
221
274
|
}
|
|
222
275
|
|
|
223
276
|
protected async clearParameterIndexes(signal?: AbortSignal): Promise<void> {
|
|
224
|
-
await
|
|
277
|
+
await clearCollectionInIdBatches(
|
|
278
|
+
this.logger,
|
|
225
279
|
'parameter index',
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
),
|
|
233
|
-
signal
|
|
280
|
+
this.db.parameterIndexV1,
|
|
281
|
+
{
|
|
282
|
+
'key.g': this.replicationStreamId
|
|
283
|
+
},
|
|
284
|
+
signal,
|
|
285
|
+
this.clearBatchThrottleRate
|
|
234
286
|
);
|
|
235
287
|
}
|
|
236
288
|
|
|
237
289
|
protected async clearSourceRecords(signal?: AbortSignal): Promise<void> {
|
|
238
|
-
await
|
|
290
|
+
await clearCollectionInIdRanges(
|
|
291
|
+
this.logger,
|
|
239
292
|
'source records',
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
),
|
|
247
|
-
signal
|
|
293
|
+
this.db.sourceRecordsV1,
|
|
294
|
+
{
|
|
295
|
+
_id: idPrefixFilter<SourceKey>({ g: this.replicationStreamId }, ['t', 'k'])
|
|
296
|
+
},
|
|
297
|
+
signal,
|
|
298
|
+
this.clearBatchThrottleRate
|
|
248
299
|
);
|
|
249
300
|
}
|
|
250
301
|
|
|
251
302
|
protected async clearBucketState(signal?: AbortSignal): Promise<void> {
|
|
252
|
-
await
|
|
303
|
+
await clearCollectionInIdRanges(
|
|
304
|
+
this.logger,
|
|
253
305
|
'bucket state',
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
),
|
|
261
|
-
signal
|
|
306
|
+
this.db.bucketStateV1,
|
|
307
|
+
{
|
|
308
|
+
_id: idPrefixFilter<BucketStateDocument['_id']>({ g: this.replicationStreamId }, ['b'])
|
|
309
|
+
},
|
|
310
|
+
signal,
|
|
311
|
+
this.clearBatchThrottleRate
|
|
262
312
|
);
|
|
263
313
|
}
|
|
264
314
|
|
|
265
315
|
protected async clearSourceTables(signal?: AbortSignal): Promise<void> {
|
|
266
|
-
await
|
|
267
|
-
'source tables',
|
|
316
|
+
await retryOnMongoMaxTimeMSExpired(
|
|
268
317
|
() =>
|
|
269
|
-
this.db.
|
|
318
|
+
this.db.sourceTablesV1(this.replicationStreamId).deleteMany(
|
|
270
319
|
{
|
|
271
|
-
group_id: this.
|
|
320
|
+
group_id: this.replicationStreamId
|
|
272
321
|
},
|
|
273
322
|
{ maxTimeMS: lib_mongo.db.MONGO_CLEAR_OPERATION_TIMEOUT_MS }
|
|
274
323
|
),
|
|
275
|
-
|
|
324
|
+
{
|
|
325
|
+
signal,
|
|
326
|
+
abortMessage: 'Aborted clearing data',
|
|
327
|
+
// This is a fairly long delay - only expected to hit this when the storage database is under high load.
|
|
328
|
+
retryDelayMs: lib_mongo.db.MONGO_CLEAR_OPERATION_TIMEOUT_MS,
|
|
329
|
+
onRetry: () => {
|
|
330
|
+
this.logger.info(
|
|
331
|
+
`Clearing batch of source tables timed out after ${lib_mongo.db.MONGO_CLEAR_OPERATION_TIMEOUT_MS}ms, retrying...`
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
276
335
|
);
|
|
277
336
|
}
|
|
278
337
|
|
|
@@ -283,14 +342,14 @@ export class MongoSyncBucketStorageV1 extends MongoSyncBucketStorage {
|
|
|
283
342
|
}
|
|
284
343
|
|
|
285
344
|
protected getParameterBucketChangesImpl(
|
|
286
|
-
options:
|
|
345
|
+
options: MongoGetCheckpointChangesOptions
|
|
287
346
|
): Promise<Pick<CheckpointChanges, 'updatedParameterLookups' | 'invalidateParameterBuckets'>> {
|
|
288
347
|
return getParameterBucketChangesV1(this.versionContext, options);
|
|
289
348
|
}
|
|
290
349
|
}
|
|
291
350
|
|
|
292
351
|
export async function getParameterSetsV1(
|
|
293
|
-
ctx:
|
|
352
|
+
ctx: MongoSyncBucketStorageContextV1,
|
|
294
353
|
checkpoint: MongoSyncBucketStorageCheckpoint,
|
|
295
354
|
lookups: ScopedParameterLookup[],
|
|
296
355
|
limit: number
|
|
@@ -306,7 +365,7 @@ export async function getParameterSetsV1(
|
|
|
306
365
|
[
|
|
307
366
|
{
|
|
308
367
|
$match: {
|
|
309
|
-
'key.g': ctx.
|
|
368
|
+
'key.g': ctx.replicationStreamId,
|
|
310
369
|
lookup: { $in: lookupFilter },
|
|
311
370
|
_id: { $lte: checkpoint.checkpoint }
|
|
312
371
|
}
|
|
@@ -364,31 +423,44 @@ export async function getParameterSetsV1(
|
|
|
364
423
|
}
|
|
365
424
|
|
|
366
425
|
export async function* getBucketDataBatchV1(
|
|
367
|
-
ctx:
|
|
368
|
-
checkpoint:
|
|
426
|
+
ctx: MongoSyncBucketStorageContextV1,
|
|
427
|
+
checkpoint: MongoSyncBucketStorageCheckpoint,
|
|
369
428
|
dataBuckets: storage.BucketDataRequest[],
|
|
370
429
|
options?: storage.BucketDataBatchOptions
|
|
371
430
|
): AsyncIterable<storage.SyncBucketDataChunk> {
|
|
372
431
|
if (dataBuckets.length == 0) {
|
|
373
432
|
return;
|
|
374
433
|
}
|
|
434
|
+
const readPreference = options?.requestHint == 'bulk' ? ctx.readPreference : undefined;
|
|
435
|
+
const readConcern = ctx.readPreference == null ? undefined : 'majority';
|
|
436
|
+
const session =
|
|
437
|
+
readPreference == null || checkpoint.snapshotTime == null
|
|
438
|
+
? undefined
|
|
439
|
+
: ctx.db.client.startSession({ causalConsistency: true });
|
|
440
|
+
await using _ = { [Symbol.asyncDispose]: async () => session?.endSession() };
|
|
441
|
+
|
|
442
|
+
if (session != null) {
|
|
443
|
+
session.advanceOperationTime(checkpoint.snapshotTime);
|
|
444
|
+
session.advanceClusterTime(checkpoint.clusterTime);
|
|
445
|
+
}
|
|
446
|
+
|
|
375
447
|
let filters: mongo.Filter<BucketDataDocumentV1>[] = [];
|
|
376
448
|
const bucketMap = new Map(dataBuckets.map((request) => [request.bucket, request.start]));
|
|
377
449
|
|
|
378
|
-
if (checkpoint == null) {
|
|
450
|
+
if (checkpoint.checkpoint == null) {
|
|
379
451
|
throw new Error('checkpoint is null');
|
|
380
452
|
}
|
|
381
|
-
const end = checkpoint;
|
|
453
|
+
const end = checkpoint.checkpoint;
|
|
382
454
|
for (let { bucket: name, start } of dataBuckets) {
|
|
383
455
|
filters.push({
|
|
384
456
|
_id: {
|
|
385
457
|
$gt: {
|
|
386
|
-
g: ctx.
|
|
458
|
+
g: ctx.replicationStreamId,
|
|
387
459
|
b: name,
|
|
388
460
|
o: start
|
|
389
461
|
},
|
|
390
462
|
$lte: {
|
|
391
|
-
g: ctx.
|
|
463
|
+
g: ctx.replicationStreamId,
|
|
392
464
|
b: name,
|
|
393
465
|
o: end as any
|
|
394
466
|
}
|
|
@@ -399,12 +471,16 @@ export async function* getBucketDataBatchV1(
|
|
|
399
471
|
const batchLimit = options?.limit ?? storage.DEFAULT_DOCUMENT_BATCH_LIMIT;
|
|
400
472
|
const chunkSizeLimitBytes = options?.chunkLimitBytes ?? storage.DEFAULT_DOCUMENT_CHUNK_LIMIT_BYTES;
|
|
401
473
|
|
|
474
|
+
// raw: true returns Buffers, but the driver typing doesn't reflect that
|
|
475
|
+
// without an explicit cast to FindCursor<Buffer>.
|
|
402
476
|
const cursor = ctx.db.bucket_data.find(
|
|
403
477
|
{
|
|
404
478
|
$or: filters
|
|
405
479
|
},
|
|
406
480
|
{
|
|
407
|
-
session
|
|
481
|
+
session,
|
|
482
|
+
readPreference,
|
|
483
|
+
readConcern,
|
|
408
484
|
sort: { _id: 1 },
|
|
409
485
|
limit: batchLimit,
|
|
410
486
|
batchSize: batchLimit + 1,
|
|
@@ -481,14 +557,14 @@ export async function* getBucketDataBatchV1(
|
|
|
481
557
|
}
|
|
482
558
|
|
|
483
559
|
export async function getDataBucketChangesV1(
|
|
484
|
-
ctx:
|
|
560
|
+
ctx: MongoSyncBucketStorageContextV1,
|
|
485
561
|
options: GetCheckpointChangesOptions
|
|
486
562
|
): Promise<Pick<CheckpointChanges, 'updatedDataBuckets' | 'invalidateDataBuckets'>> {
|
|
487
563
|
const limit = 1000;
|
|
488
564
|
const bucketStateUpdates = await ctx.db.bucketStateV1
|
|
489
565
|
.find(
|
|
490
566
|
{
|
|
491
|
-
'_id.g': ctx.
|
|
567
|
+
'_id.g': ctx.replicationStreamId,
|
|
492
568
|
last_op: { $gt: options.lastCheckpoint.checkpoint }
|
|
493
569
|
},
|
|
494
570
|
{
|
|
@@ -511,27 +587,48 @@ export async function getDataBucketChangesV1(
|
|
|
511
587
|
};
|
|
512
588
|
}
|
|
513
589
|
|
|
590
|
+
/**
|
|
591
|
+
* Query the parameter entries changed between the two checkpoints, to determine which parameter
|
|
592
|
+
* lookups need to be re-evaluated.
|
|
593
|
+
*
|
|
594
|
+
* This runs at the next checkpoint's snapshot, so it still sees entries that parameter compaction
|
|
595
|
+
* deleted after that snapshot. Compaction that deleted entries before the snapshot is covered by
|
|
596
|
+
* the invalidation fence, checked before we get here.
|
|
597
|
+
*/
|
|
514
598
|
export async function getParameterBucketChangesV1(
|
|
515
|
-
ctx:
|
|
516
|
-
options:
|
|
599
|
+
ctx: MongoSyncBucketStorageContextV1,
|
|
600
|
+
options: MongoGetCheckpointChangesOptions
|
|
517
601
|
): Promise<Pick<CheckpointChanges, 'updatedParameterLookups' | 'invalidateParameterBuckets'>> {
|
|
518
602
|
const limit = 1000;
|
|
519
|
-
const parameterUpdates = await ctx.db.
|
|
520
|
-
.
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
projection: {
|
|
527
|
-
lookup: 1
|
|
603
|
+
const parameterUpdates = await ctx.db.client.withSession({ snapshot: true }, async (session) => {
|
|
604
|
+
setSessionSnapshotTime(session, options.nextCheckpoint.snapshotTime);
|
|
605
|
+
return await ctx.db.parameterIndexV1
|
|
606
|
+
.find(
|
|
607
|
+
{
|
|
608
|
+
_id: { $gt: options.lastCheckpoint.checkpoint, $lte: options.nextCheckpoint.checkpoint },
|
|
609
|
+
'key.g': ctx.replicationStreamId
|
|
528
610
|
},
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
611
|
+
{
|
|
612
|
+
session,
|
|
613
|
+
readConcern: 'snapshot',
|
|
614
|
+
projection: {
|
|
615
|
+
lookup: 1
|
|
616
|
+
},
|
|
617
|
+
limit: limit + 1,
|
|
618
|
+
batchSize: limit + 2,
|
|
619
|
+
singleBatch: true
|
|
620
|
+
}
|
|
621
|
+
)
|
|
622
|
+
.toArray()
|
|
623
|
+
.catch((e) => {
|
|
624
|
+
// Includes the case where the checkpoint snapshot has expired. Degrading to
|
|
625
|
+
// invalidateParameterBuckets would be safe in itself - it reads nothing - but it gains
|
|
626
|
+
// nothing: the caller responds to that by re-evaluating the parameter queries at this
|
|
627
|
+
// same snapshot, which fails too. The checkpoint has to be refetched instead, which is
|
|
628
|
+
// what the existing sync retry behavior does.
|
|
629
|
+
throw lib_mongo.mapQueryError(e, 'while querying parameter changes');
|
|
630
|
+
});
|
|
631
|
+
});
|
|
535
632
|
const invalidateParameterUpdates = parameterUpdates.length > limit;
|
|
536
633
|
|
|
537
634
|
return {
|