@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,45 +1,66 @@
|
|
|
1
1
|
import { mongo } from '@powersync/lib-service-mongodb';
|
|
2
2
|
import { BaseObserver, DO_NOT_LOG, Logger } from '@powersync/lib-services-framework';
|
|
3
|
-
import { CheckpointChanges,
|
|
3
|
+
import { CheckpointChanges, CompactInitialReplicationOptions, CompactInitialReplicationResults, GetCheckpointChangesOptions, InternalOpId, ReplicationStreamStorageIds, storage, utils, WatchWriteCheckpointOptions } from '@powersync/service-core';
|
|
4
4
|
import { HydratedSyncConfig, ParameterLookupRows, ScopedParameterLookup } from '@powersync/service-sync-rules';
|
|
5
|
-
import * as bson from 'bson';
|
|
6
5
|
import { MongoBucketStorage } from '../MongoBucketStorage.js';
|
|
7
|
-
import {
|
|
6
|
+
import { MongoGetCheckpointChangesOptions, MongoSyncBucketStorageCheckpoint } from './common/MongoSyncBucketStorageCheckpoint.js';
|
|
8
7
|
import type { VersionedPowerSyncMongo } from './db.js';
|
|
9
8
|
import { StorageConfig } from './models.js';
|
|
10
9
|
import { MongoBucketBatchOptions } from './MongoBucketBatch.js';
|
|
11
10
|
import { MongoChecksumOptions, MongoChecksums } from './MongoChecksums.js';
|
|
12
11
|
import { MongoCompactOptions, MongoCompactor } from './MongoCompactor.js';
|
|
13
12
|
import { MongoParameterCompactor } from './MongoParameterCompactor.js';
|
|
14
|
-
import {
|
|
13
|
+
import { MongoParsedSyncConfigSet } from './MongoParsedSyncConfigSet.js';
|
|
14
|
+
import { MongoPersistedReplicationStream } from './MongoPersistedReplicationStream.js';
|
|
15
|
+
import { MongoCheckpointAPIOptions, MongoWriteCheckpointAPI } from './MongoWriteCheckpointAPI.js';
|
|
16
|
+
import { ObjectStorage } from './v3/object-storage/ObjectStorage.js';
|
|
15
17
|
export interface MongoSyncBucketStorageOptions {
|
|
16
|
-
checksumOptions?: Omit<MongoChecksumOptions, 'storageConfig'
|
|
18
|
+
checksumOptions?: Omit<MongoChecksumOptions, 'storageConfig'>;
|
|
19
|
+
readPreference?: mongo.ReadPreference;
|
|
20
|
+
checksumCacheTtlMs?: number;
|
|
21
|
+
clearBatchThrottleRate?: number;
|
|
17
22
|
storageConfig: StorageConfig;
|
|
23
|
+
objectStorage?: ObjectStorage;
|
|
24
|
+
inlineThresholdBytes?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The stream state read for a checkpoint. All fields must come from the same snapshot.
|
|
28
|
+
*/
|
|
29
|
+
export interface MongoCheckpointState {
|
|
30
|
+
checkpoint: InternalOpId;
|
|
31
|
+
lsn: string | null;
|
|
32
|
+
/** See {@link MongoSyncBucketStorageCheckpoint.parameterChangesInvalidBefore}. */
|
|
33
|
+
parameterChangesInvalidBefore: InternalOpId;
|
|
18
34
|
}
|
|
19
35
|
interface InternalCheckpointChanges extends CheckpointChanges {
|
|
20
36
|
updatedWriteCheckpoints: Map<string, bigint>;
|
|
21
37
|
invalidateWriteCheckpoints: boolean;
|
|
22
38
|
}
|
|
23
|
-
interface WriterSyncState {
|
|
24
|
-
lastCheckpointLsn: string | null;
|
|
25
|
-
resumeFromLsn: string | null;
|
|
26
|
-
keepaliveOp: InternalOpId | null;
|
|
27
|
-
syncConfigId?: bson.ObjectId | null;
|
|
28
|
-
}
|
|
29
39
|
export declare abstract class MongoSyncBucketStorage extends BaseObserver<storage.SyncRulesBucketStorageListener> implements storage.SyncRulesBucketStorage {
|
|
30
40
|
#private;
|
|
31
41
|
readonly factory: MongoBucketStorage;
|
|
32
|
-
readonly
|
|
33
|
-
|
|
34
|
-
readonly
|
|
42
|
+
readonly replicationStreamId: number;
|
|
43
|
+
readonly replicationStream: MongoPersistedReplicationStream;
|
|
44
|
+
readonly replicationStreamName: string;
|
|
35
45
|
readonly db: VersionedPowerSyncMongo;
|
|
36
46
|
[DO_NOT_LOG]: boolean;
|
|
37
47
|
readonly checksums: MongoChecksums;
|
|
38
|
-
|
|
48
|
+
readonly objectStorage?: ObjectStorage;
|
|
49
|
+
readonly inlineThresholdBytes: number;
|
|
50
|
+
/**
|
|
51
|
+
* Canonical parsed sync config sets, keyed by defaultSchema.
|
|
52
|
+
*
|
|
53
|
+
* Entries are never evicted: each parse options value maps to exactly one parsed set for
|
|
54
|
+
* the lifetime of this storage instance, so parsed source objects and mappings always
|
|
55
|
+
* stay associated.
|
|
56
|
+
*/
|
|
57
|
+
private readonly parsedSyncConfigSets;
|
|
39
58
|
private writeCheckpointAPI;
|
|
40
59
|
readonly logger: Logger;
|
|
41
60
|
readonly storageConfig: StorageConfig;
|
|
42
|
-
|
|
61
|
+
readonly readPreference: mongo.ReadPreference | undefined;
|
|
62
|
+
readonly clearBatchThrottleRate: number;
|
|
63
|
+
constructor(factory: MongoBucketStorage, replicationStreamId: number, replicationStream: MongoPersistedReplicationStream, replicationStreamName: string, writeCheckpointMode: storage.WriteCheckpointMode | undefined, options: MongoSyncBucketStorageOptions);
|
|
43
64
|
/**
|
|
44
65
|
* Not for external use - public here for tests only.
|
|
45
66
|
*
|
|
@@ -47,47 +68,65 @@ export declare abstract class MongoSyncBucketStorage extends BaseObserver<storag
|
|
|
47
68
|
*/
|
|
48
69
|
abstract createMongoCompactor(options: MongoCompactOptions): MongoCompactor;
|
|
49
70
|
protected abstract createMongoChecksums(options: MongoSyncBucketStorageOptions): MongoChecksums;
|
|
71
|
+
protected createWriteCheckpointAPI(options: MongoCheckpointAPIOptions): MongoWriteCheckpointAPI;
|
|
50
72
|
protected abstract createMongoParameterCompactor(checkpoint: InternalOpId, options: storage.CompactOptions): MongoParameterCompactor;
|
|
73
|
+
/** MongoDB parameter compaction uses a persisted operation-id cursor. */
|
|
74
|
+
supportsIncrementalParameterCompaction(): boolean;
|
|
51
75
|
get writeCheckpointMode(): storage.WriteCheckpointMode;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Persisted storage ids of all sync configs in this replication stream. Parse-free.
|
|
78
|
+
*/
|
|
79
|
+
get storageIds(): ReplicationStreamStorageIds;
|
|
80
|
+
setWriteCheckpointMode(config: storage.WriteCheckpointModeConfig): void;
|
|
81
|
+
createManagedWriteCheckpoints(checkpoints: storage.ManagedWriteCheckpointOptions[]): Promise<storage.CreateManagedWriteCheckpointsResult>;
|
|
56
82
|
lastWriteCheckpoint(filters: storage.SyncStorageLastWriteCheckpointFilters): Promise<bigint | null>;
|
|
57
|
-
|
|
83
|
+
getParsedSyncConfigSet(options: storage.ParseSyncConfigOptions): MongoParsedSyncConfigSet;
|
|
84
|
+
getParsedSyncRules(options: storage.ParseSyncConfigOptions): HydratedSyncConfig;
|
|
58
85
|
getCheckpoint(): Promise<storage.ReplicationCheckpoint>;
|
|
59
|
-
protected abstract fetchCheckpointState(session: mongo.ClientSession): Promise<
|
|
60
|
-
checkpoint: bigint;
|
|
61
|
-
lsn: string | null;
|
|
62
|
-
} | null>;
|
|
86
|
+
protected abstract fetchCheckpointState(session: mongo.ClientSession): Promise<MongoCheckpointState | null>;
|
|
63
87
|
getCheckpointInternal(): Promise<storage.ReplicationCheckpoint | null>;
|
|
64
88
|
protected abstract initializeVersionStorage(): Promise<void>;
|
|
65
89
|
private initializeStorage;
|
|
66
|
-
|
|
67
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Create the version-specific writer. Implementations fetch their own resume state
|
|
92
|
+
* (e.g. resume LSN, v1 keepalive op) and construct the batch from
|
|
93
|
+
* {@link writerBatchOptions} plus the version-specific fields.
|
|
94
|
+
*/
|
|
95
|
+
protected abstract createWriterImpl(options: storage.CreateWriterOptions): Promise<storage.BucketStorageBatch>;
|
|
96
|
+
/**
|
|
97
|
+
* The version-independent part of the batch options.
|
|
98
|
+
*/
|
|
99
|
+
protected writerBatchOptions(options: storage.CreateWriterOptions): Omit<MongoBucketBatchOptions, 'resumeFromLsn'>;
|
|
68
100
|
createWriter(options: storage.CreateWriterOptions): Promise<storage.BucketStorageBatch>;
|
|
69
101
|
startBatch(options: storage.CreateWriterOptions, callback: (batch: storage.BucketStorageBatch) => Promise<void>): Promise<storage.FlushedResult | null>;
|
|
70
102
|
protected abstract getParameterSetsImpl(checkpoint: MongoReplicationCheckpoint, lookups: ScopedParameterLookup[], limit: number): Promise<ParameterLookupRows[]>;
|
|
71
103
|
getParameterSets(checkpoint: MongoReplicationCheckpoint, lookups: ScopedParameterLookup[], limit: number): Promise<ParameterLookupRows[]>;
|
|
72
|
-
protected abstract getBucketDataBatchImpl(checkpoint:
|
|
73
|
-
getBucketDataBatch(checkpoint:
|
|
74
|
-
getChecksums(checkpoint:
|
|
104
|
+
protected abstract getBucketDataBatchImpl(checkpoint: MongoReplicationCheckpoint, dataBuckets: storage.BucketDataRequest[], options?: storage.BucketDataBatchOptions): AsyncIterable<storage.SyncBucketDataChunk | storage.SyncBucketDataBatchEnd>;
|
|
105
|
+
getBucketDataBatch(checkpoint: storage.ReplicationCheckpoint, dataBuckets: storage.BucketDataRequest[], options?: storage.BucketDataBatchOptions): AsyncIterable<storage.SyncBucketDataChunk | storage.SyncBucketDataBatchEnd>;
|
|
106
|
+
getChecksums(checkpoint: storage.ReplicationCheckpoint, buckets: storage.BucketChecksumRequest[], options?: storage.BucketChecksumOptions): Promise<utils.ChecksumMap>;
|
|
75
107
|
clearChecksumCache(): void;
|
|
76
108
|
protected abstract terminateSyncRuleState(): Promise<void>;
|
|
77
109
|
terminate(options?: storage.TerminateOptions): Promise<void>;
|
|
78
|
-
protected abstract getStatusImpl(): Promise<storage.
|
|
79
|
-
getStatus(): Promise<storage.
|
|
110
|
+
protected abstract getStatusImpl(): Promise<storage.ReplicationStreamStatus>;
|
|
111
|
+
getStatus(): Promise<storage.ReplicationStreamStatus>;
|
|
80
112
|
protected abstract clearBucketData(signal?: AbortSignal): Promise<void>;
|
|
81
113
|
protected abstract clearParameterIndexes(signal?: AbortSignal): Promise<void>;
|
|
82
114
|
protected abstract clearSourceRecords(signal?: AbortSignal): Promise<void>;
|
|
83
115
|
protected abstract clearBucketState(signal?: AbortSignal): Promise<void>;
|
|
84
116
|
protected abstract clearSourceTables(signal?: AbortSignal): Promise<void>;
|
|
117
|
+
protected clearCustomCheckpointRequests(_signal?: AbortSignal): Promise<void>;
|
|
85
118
|
protected abstract clearSyncRuleState(): Promise<void>;
|
|
86
119
|
clear(options?: storage.ClearStorageOptions): Promise<void>;
|
|
87
|
-
protected clearDeleteMany(label: string, operation: () => Promise<mongo.DeleteResult>, signal?: AbortSignal): Promise<void>;
|
|
88
120
|
reportError(e: any): Promise<void>;
|
|
89
121
|
compact(options?: storage.CompactOptions): Promise<void>;
|
|
90
|
-
|
|
122
|
+
abstract compactInitialReplication(options: CompactInitialReplicationOptions): Promise<CompactInitialReplicationResults>;
|
|
123
|
+
/**
|
|
124
|
+
* The highest op id persisted for this stream, whether or not covered by a checkpoint.
|
|
125
|
+
*
|
|
126
|
+
* Used as the default `maxOpId` for {@link compactInitialReplication}, which runs after
|
|
127
|
+
* initial replication but before the first checkpoint exists.
|
|
128
|
+
*/
|
|
129
|
+
protected abstract fetchPersistedOpHead(): Promise<InternalOpId | null>;
|
|
91
130
|
private watchActiveCheckpoint;
|
|
92
131
|
private readonly sharedIter;
|
|
93
132
|
watchCheckpointChanges(options: WatchWriteCheckpointOptions): AsyncIterable<storage.StorageCheckpointUpdate>;
|
|
@@ -95,18 +134,23 @@ export declare abstract class MongoSyncBucketStorage extends BaseObserver<storag
|
|
|
95
134
|
private checkpointTimeoutStream;
|
|
96
135
|
protected abstract getDataBucketChangesImpl(options: GetCheckpointChangesOptions): Promise<Pick<CheckpointChanges, 'updatedDataBuckets' | 'invalidateDataBuckets'>>;
|
|
97
136
|
private getDataBucketChanges;
|
|
98
|
-
protected abstract getParameterBucketChangesImpl(options:
|
|
137
|
+
protected abstract getParameterBucketChangesImpl(options: MongoGetCheckpointChangesOptions): Promise<Pick<CheckpointChanges, 'updatedParameterLookups' | 'invalidateParameterBuckets'>>;
|
|
99
138
|
private getParameterBucketChanges;
|
|
100
139
|
private checkpointChangesCache;
|
|
101
140
|
getCheckpointChanges(options: GetCheckpointChangesOptions): Promise<InternalCheckpointChanges>;
|
|
102
141
|
private getCheckpointChangesInternal;
|
|
103
142
|
}
|
|
104
|
-
declare class MongoReplicationCheckpoint implements
|
|
143
|
+
declare class MongoReplicationCheckpoint implements MongoSyncBucketStorageCheckpoint {
|
|
105
144
|
#private;
|
|
106
145
|
readonly checkpoint: InternalOpId;
|
|
107
146
|
readonly lsn: string | null;
|
|
108
147
|
snapshotTime: mongo.Timestamp;
|
|
109
|
-
|
|
148
|
+
clusterTime: mongo.ClusterTime;
|
|
149
|
+
/** Captured in the same snapshot as the checkpoint. */
|
|
150
|
+
readonly parameterChangesInvalidBefore: InternalOpId;
|
|
151
|
+
constructor(storage: MongoSyncBucketStorage, checkpoint: InternalOpId, lsn: string | null, snapshotTime: mongo.Timestamp, clusterTime: mongo.ClusterTime,
|
|
152
|
+
/** Captured in the same snapshot as the checkpoint. */
|
|
153
|
+
parameterChangesInvalidBefore: InternalOpId);
|
|
110
154
|
getParameterSets(lookups: ScopedParameterLookup[], limit: number): Promise<ParameterLookupRows[]>;
|
|
111
155
|
}
|
|
112
156
|
export {};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as lib_mongo from '@powersync/lib-service-mongodb';
|
|
2
|
-
import { BaseObserver, DO_NOT_LOG, ReplicationAbortedError, ServiceAssertionError } from '@powersync/lib-services-framework';
|
|
3
|
-
import { BroadcastIterable, CHECKPOINT_INVALIDATE_ALL, mergeAsyncIterables, storage } from '@powersync/service-core';
|
|
2
|
+
import { BaseObserver, logger as defaultLogger, DO_NOT_LOG, ReplicationAbortedError, ServiceAssertionError } from '@powersync/lib-services-framework';
|
|
3
|
+
import { BroadcastIterable, CHECKPOINT_INVALIDATE_ALL, mergeAsyncIterables, storage, SyncRuleState } from '@powersync/service-core';
|
|
4
4
|
import { LRUCache } from 'lru-cache';
|
|
5
5
|
import * as timers from 'timers/promises';
|
|
6
|
-
import {
|
|
6
|
+
import { DEFAULT_CLEAR_BATCH_THROTTLE_RATE } from '../../types/types.js';
|
|
7
|
+
import { DEFAULT_INLINE_THRESHOLD_BYTES } from './common/PersistedBatch.js';
|
|
7
8
|
import { MongoWriteCheckpointAPI } from './MongoWriteCheckpointAPI.js';
|
|
8
9
|
/**
|
|
9
10
|
* Only keep checkpoints around for a minute, before fetching a fresh one.
|
|
@@ -17,64 +18,102 @@ import { MongoWriteCheckpointAPI } from './MongoWriteCheckpointAPI.js';
|
|
|
17
18
|
const CHECKPOINT_TIMEOUT_MS = 60_000;
|
|
18
19
|
export class MongoSyncBucketStorage extends BaseObserver {
|
|
19
20
|
factory;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
replicationStreamId;
|
|
22
|
+
replicationStream;
|
|
23
|
+
replicationStreamName;
|
|
23
24
|
db;
|
|
24
25
|
[DO_NOT_LOG] = true;
|
|
25
26
|
checksums;
|
|
26
|
-
|
|
27
|
+
objectStorage;
|
|
28
|
+
inlineThresholdBytes;
|
|
29
|
+
/**
|
|
30
|
+
* Canonical parsed sync config sets, keyed by defaultSchema.
|
|
31
|
+
*
|
|
32
|
+
* Entries are never evicted: each parse options value maps to exactly one parsed set for
|
|
33
|
+
* the lifetime of this storage instance, so parsed source objects and mappings always
|
|
34
|
+
* stay associated.
|
|
35
|
+
*/
|
|
36
|
+
parsedSyncConfigSets = new Map();
|
|
27
37
|
writeCheckpointAPI;
|
|
28
38
|
logger;
|
|
29
39
|
storageConfig;
|
|
40
|
+
readPreference;
|
|
41
|
+
clearBatchThrottleRate;
|
|
30
42
|
#storageInitialized = false;
|
|
31
|
-
constructor(factory,
|
|
43
|
+
constructor(factory, replicationStreamId, replicationStream, replicationStreamName, writeCheckpointMode, options) {
|
|
32
44
|
super();
|
|
33
45
|
this.factory = factory;
|
|
34
|
-
this.
|
|
35
|
-
this.
|
|
36
|
-
this.
|
|
46
|
+
this.replicationStreamId = replicationStreamId;
|
|
47
|
+
this.replicationStream = replicationStream;
|
|
48
|
+
this.replicationStreamName = replicationStreamName;
|
|
37
49
|
this.storageConfig = options.storageConfig;
|
|
50
|
+
this.objectStorage = options.objectStorage;
|
|
51
|
+
// Keep small chunks inline in MongoDB rather than offloading them to S3.
|
|
52
|
+
// Configurable via object_storage.inline_threshold_bytes.
|
|
53
|
+
this.inlineThresholdBytes = options.inlineThresholdBytes ?? DEFAULT_INLINE_THRESHOLD_BYTES;
|
|
54
|
+
this.readPreference = options.readPreference;
|
|
55
|
+
this.clearBatchThrottleRate = options.clearBatchThrottleRate ?? DEFAULT_CLEAR_BATCH_THROTTLE_RATE;
|
|
38
56
|
this.db = factory.db.versioned(this.storageConfig);
|
|
39
57
|
this.checksums = this.createMongoChecksums(options);
|
|
40
|
-
this.writeCheckpointAPI =
|
|
58
|
+
this.writeCheckpointAPI = this.createWriteCheckpointAPI({
|
|
41
59
|
db: this.db,
|
|
42
|
-
mode: writeCheckpointMode ?? storage.WriteCheckpointMode.MANAGED,
|
|
43
|
-
|
|
60
|
+
writeCheckpointMode: { mode: writeCheckpointMode ?? storage.WriteCheckpointMode.MANAGED },
|
|
61
|
+
replicationStreamId
|
|
44
62
|
});
|
|
45
|
-
|
|
63
|
+
// Include both replication stream name and sync config version labels in log prefix.
|
|
64
|
+
// Examples:
|
|
65
|
+
// No sync config with a label: [stream]
|
|
66
|
+
// All sync configs have a label: [stream][v5,v6]
|
|
67
|
+
// Mixed: [stream][?,v6]
|
|
68
|
+
const hasVersionLabel = replicationStream.syncConfigContent.some((config) => config.version_label != null);
|
|
69
|
+
const versionLabels = hasVersionLabel
|
|
70
|
+
? replicationStream.syncConfigContent.map((config) => config.version_label ?? '?')
|
|
71
|
+
: [];
|
|
72
|
+
this.logger =
|
|
73
|
+
versionLabels.length == 0
|
|
74
|
+
? replicationStream.logger
|
|
75
|
+
: defaultLogger.child({
|
|
76
|
+
prefix: `[${replicationStreamName}][${versionLabels.join(',')}] `
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
createWriteCheckpointAPI(options) {
|
|
80
|
+
return new MongoWriteCheckpointAPI(options);
|
|
81
|
+
}
|
|
82
|
+
/** MongoDB parameter compaction uses a persisted operation-id cursor. */
|
|
83
|
+
supportsIncrementalParameterCompaction() {
|
|
84
|
+
return true;
|
|
46
85
|
}
|
|
47
86
|
get writeCheckpointMode() {
|
|
48
87
|
return this.writeCheckpointAPI.writeCheckpointMode;
|
|
49
88
|
}
|
|
50
|
-
|
|
51
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Persisted storage ids of all sync configs in this replication stream. Parse-free.
|
|
91
|
+
*/
|
|
92
|
+
get storageIds() {
|
|
93
|
+
return this.replicationStream.storageIds;
|
|
52
94
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
db: this.db,
|
|
56
|
-
group_id: this.group_id,
|
|
57
|
-
mapping: this.mapping
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
setWriteCheckpointMode(mode) {
|
|
61
|
-
this.writeCheckpointAPI.setWriteCheckpointMode(mode);
|
|
95
|
+
setWriteCheckpointMode(config) {
|
|
96
|
+
this.writeCheckpointAPI.setWriteCheckpointMode(config);
|
|
62
97
|
}
|
|
63
|
-
|
|
64
|
-
return this.writeCheckpointAPI.
|
|
98
|
+
createManagedWriteCheckpoints(checkpoints) {
|
|
99
|
+
return this.writeCheckpointAPI.createManagedWriteCheckpoints(checkpoints);
|
|
65
100
|
}
|
|
66
101
|
lastWriteCheckpoint(filters) {
|
|
67
102
|
return this.writeCheckpointAPI.lastWriteCheckpoint({
|
|
68
103
|
...filters,
|
|
69
|
-
sync_rules_id: this.
|
|
104
|
+
sync_rules_id: this.replicationStreamId
|
|
70
105
|
});
|
|
71
106
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
|
|
107
|
+
getParsedSyncConfigSet(options) {
|
|
108
|
+
let parsed = this.parsedSyncConfigSets.get(options.defaultSchema);
|
|
109
|
+
if (parsed == null) {
|
|
110
|
+
parsed = this.replicationStream.parsed(options);
|
|
111
|
+
this.parsedSyncConfigSets.set(options.defaultSchema, parsed);
|
|
76
112
|
}
|
|
77
|
-
return
|
|
113
|
+
return parsed;
|
|
114
|
+
}
|
|
115
|
+
getParsedSyncRules(options) {
|
|
116
|
+
return this.getParsedSyncConfigSet(options).hydratedSyncConfig;
|
|
78
117
|
}
|
|
79
118
|
async getCheckpoint() {
|
|
80
119
|
return (await this.getCheckpointInternal()) ?? new EmptyReplicationCheckpoint();
|
|
@@ -86,41 +125,47 @@ export class MongoSyncBucketStorage extends BaseObserver {
|
|
|
86
125
|
return null;
|
|
87
126
|
}
|
|
88
127
|
const snapshotTime = session.snapshotTime;
|
|
128
|
+
const clusterTime = session.clusterTime;
|
|
89
129
|
if (snapshotTime == null) {
|
|
90
130
|
throw new ServiceAssertionError('Missing snapshotTime in getCheckpoint()');
|
|
91
131
|
}
|
|
92
|
-
|
|
132
|
+
if (clusterTime == null) {
|
|
133
|
+
throw new ServiceAssertionError('Missing clusterTime in getCheckpoint()');
|
|
134
|
+
}
|
|
135
|
+
return new MongoReplicationCheckpoint(this, state.checkpoint, state.lsn, snapshotTime, clusterTime, state.parameterChangesInvalidBefore);
|
|
93
136
|
});
|
|
94
137
|
}
|
|
95
138
|
async initializeStorage() {
|
|
96
139
|
if (this.#storageInitialized) {
|
|
97
140
|
return;
|
|
98
141
|
}
|
|
99
|
-
await this.db.initializeStreamStorage(this.
|
|
142
|
+
await this.db.initializeStreamStorage(this.replicationStreamId);
|
|
100
143
|
await this.initializeVersionStorage();
|
|
101
144
|
this.#storageInitialized = true;
|
|
102
145
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
146
|
+
/**
|
|
147
|
+
* The version-independent part of the batch options.
|
|
148
|
+
*/
|
|
149
|
+
writerBatchOptions(options) {
|
|
150
|
+
return {
|
|
107
151
|
logger: options.logger ?? this.logger,
|
|
108
152
|
db: this.db,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
slotName: this.slot_name,
|
|
113
|
-
lastCheckpointLsn: state.lastCheckpointLsn,
|
|
114
|
-
resumeFromLsn: state.resumeFromLsn,
|
|
115
|
-
keepaliveOp: state.keepaliveOp,
|
|
153
|
+
parsedSyncConfig: this.getParsedSyncConfigSet(options),
|
|
154
|
+
replicationStreamId: this.replicationStreamId,
|
|
155
|
+
replicationStreamName: this.replicationStreamName,
|
|
116
156
|
storeCurrentData: options.storeCurrentData,
|
|
117
157
|
skipExistingRows: options.skipExistingRows ?? false,
|
|
118
158
|
markRecordUnavailable: options.markRecordUnavailable,
|
|
119
159
|
hooks: options.hooks,
|
|
120
|
-
|
|
121
|
-
|
|
160
|
+
tracer: options.tracer,
|
|
161
|
+
signal: options.signal,
|
|
162
|
+
objectStorage: this.objectStorage,
|
|
163
|
+
inlineThresholdBytes: this.inlineThresholdBytes
|
|
122
164
|
};
|
|
123
|
-
|
|
165
|
+
}
|
|
166
|
+
async createWriter(options) {
|
|
167
|
+
await this.initializeStorage();
|
|
168
|
+
const writer = await this.createWriterImpl(options);
|
|
124
169
|
this.iterateListeners((cb) => cb.batchStarted?.(writer));
|
|
125
170
|
return writer;
|
|
126
171
|
}
|
|
@@ -136,8 +181,14 @@ export class MongoSyncBucketStorage extends BaseObserver {
|
|
|
136
181
|
async *getBucketDataBatch(checkpoint, dataBuckets, options) {
|
|
137
182
|
yield* this.getBucketDataBatchImpl(checkpoint, dataBuckets, options);
|
|
138
183
|
}
|
|
139
|
-
async getChecksums(checkpoint, buckets) {
|
|
140
|
-
|
|
184
|
+
async getChecksums(checkpoint, buckets, options) {
|
|
185
|
+
const mongoCheckpoint = checkpoint;
|
|
186
|
+
const snapshotTime = mongoCheckpoint.snapshotTime; // May be undefined in tests
|
|
187
|
+
return this.checksums.getChecksums(checkpoint.checkpoint, buckets, {
|
|
188
|
+
snapshotTime,
|
|
189
|
+
clusterTime: mongoCheckpoint.clusterTime,
|
|
190
|
+
readPreference: options?.requestHint == 'bulk' ? this.readPreference : undefined
|
|
191
|
+
});
|
|
141
192
|
}
|
|
142
193
|
clearChecksumCache() {
|
|
143
194
|
this.checksums.clearCache();
|
|
@@ -152,6 +203,7 @@ export class MongoSyncBucketStorage extends BaseObserver {
|
|
|
152
203
|
async getStatus() {
|
|
153
204
|
return this.getStatusImpl();
|
|
154
205
|
}
|
|
206
|
+
async clearCustomCheckpointRequests(_signal) { }
|
|
155
207
|
async clear(options) {
|
|
156
208
|
const signal = options?.signal;
|
|
157
209
|
if (signal?.aborted) {
|
|
@@ -163,22 +215,13 @@ export class MongoSyncBucketStorage extends BaseObserver {
|
|
|
163
215
|
await this.clearSourceRecords(signal);
|
|
164
216
|
await this.clearBucketState(signal);
|
|
165
217
|
await this.clearSourceTables(signal);
|
|
218
|
+
await this.clearCustomCheckpointRequests(signal);
|
|
166
219
|
this.#storageInitialized = false;
|
|
167
220
|
}
|
|
168
|
-
async clearDeleteMany(label, operation, signal) {
|
|
169
|
-
await retryOnMongoMaxTimeMSExpired(operation, {
|
|
170
|
-
signal,
|
|
171
|
-
abortMessage: 'Aborted clearing data',
|
|
172
|
-
retryDelayMs: lib_mongo.db.MONGO_CLEAR_OPERATION_TIMEOUT_MS / 5,
|
|
173
|
-
onRetry: () => {
|
|
174
|
-
this.logger.info(`Cleared batch of ${label} in ${lib_mongo.db.MONGO_CLEAR_OPERATION_TIMEOUT_MS}ms, continuing...`);
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
221
|
async reportError(e) {
|
|
179
222
|
const message = String(e.message ?? 'Replication failure');
|
|
180
223
|
await this.db.sync_rules.updateOne({
|
|
181
|
-
_id: this.
|
|
224
|
+
_id: this.replicationStreamId
|
|
182
225
|
}, {
|
|
183
226
|
$set: {
|
|
184
227
|
last_fatal_error: message,
|
|
@@ -189,29 +232,16 @@ export class MongoSyncBucketStorage extends BaseObserver {
|
|
|
189
232
|
async compact(options) {
|
|
190
233
|
let maxOpId = options?.maxOpId;
|
|
191
234
|
if (maxOpId == null) {
|
|
235
|
+
// For PROCESSING streams, this will be undefined.
|
|
192
236
|
const checkpoint = await this.getCheckpointInternal();
|
|
193
237
|
maxOpId = checkpoint?.checkpoint ?? undefined;
|
|
194
238
|
}
|
|
195
239
|
await this.createMongoCompactor({ ...options, maxOpId, logger: this.logger }).compact();
|
|
196
|
-
if (maxOpId != null && options?.compactParameterData) {
|
|
197
|
-
|
|
240
|
+
if (maxOpId != null && options?.compactParameterData && this.replicationStream.state == SyncRuleState.ACTIVE) {
|
|
241
|
+
// Use the stream-scoped logger, matching bucket compaction above.
|
|
242
|
+
await this.createMongoParameterCompactor(maxOpId, { ...options, logger: this.logger }).compact();
|
|
198
243
|
}
|
|
199
244
|
}
|
|
200
|
-
async populatePersistentChecksumCache(options) {
|
|
201
|
-
this.logger.info(`Populating persistent checksum cache...`);
|
|
202
|
-
const start = Date.now();
|
|
203
|
-
const compactor = this.createMongoCompactor({
|
|
204
|
-
...options,
|
|
205
|
-
memoryLimitMB: 0,
|
|
206
|
-
logger: this.logger
|
|
207
|
-
});
|
|
208
|
-
const result = await compactor.populateChecksums({
|
|
209
|
-
minBucketChanges: options.minBucketChanges ?? 10
|
|
210
|
-
});
|
|
211
|
-
const duration = Date.now() - start;
|
|
212
|
-
this.logger.info(`Populated persistent checksum cache in ${(duration / 1000).toFixed(1)}s`);
|
|
213
|
-
return result;
|
|
214
|
-
}
|
|
215
245
|
async *watchActiveCheckpoint(signal) {
|
|
216
246
|
if (signal.aborted) {
|
|
217
247
|
return;
|
|
@@ -239,7 +269,7 @@ export class MongoSyncBucketStorage extends BaseObserver {
|
|
|
239
269
|
for await (const nextCheckpoint of iter) {
|
|
240
270
|
if (nextCheckpoint.lsn != null && !queriedInitialWriteCheckpoint) {
|
|
241
271
|
writeCheckpoint = await this.writeCheckpointAPI.lastWriteCheckpoint({
|
|
242
|
-
sync_rules_id: this.
|
|
272
|
+
sync_rules_id: this.replicationStreamId,
|
|
243
273
|
user_id: options.user_id,
|
|
244
274
|
heads: {
|
|
245
275
|
'1': nextCheckpoint.lsn
|
|
@@ -268,7 +298,7 @@ export class MongoSyncBucketStorage extends BaseObserver {
|
|
|
268
298
|
let updatedWriteCheckpoint = updates.updatedWriteCheckpoints.get(options.user_id) ?? null;
|
|
269
299
|
if (updates.invalidateWriteCheckpoints) {
|
|
270
300
|
updatedWriteCheckpoint = await this.writeCheckpointAPI.lastWriteCheckpoint({
|
|
271
|
-
sync_rules_id: this.
|
|
301
|
+
sync_rules_id: this.replicationStreamId,
|
|
272
302
|
user_id: options.user_id,
|
|
273
303
|
heads: {
|
|
274
304
|
'1': nextCheckpoint.lsn
|
|
@@ -355,11 +385,32 @@ export class MongoSyncBucketStorage extends BaseObserver {
|
|
|
355
385
|
return this.getDataBucketChangesImpl(options);
|
|
356
386
|
}
|
|
357
387
|
async getParameterBucketChanges(options) {
|
|
358
|
-
|
|
388
|
+
const nextCheckpoint = requireMongoCheckpoint(options.nextCheckpoint);
|
|
389
|
+
if (options.lastCheckpoint.checkpoint < nextCheckpoint.parameterChangesInvalidBefore) {
|
|
390
|
+
// Parameter compaction may have deleted parameter entries in the range we'd have to query
|
|
391
|
+
// to find the individual changed lookups. Invalidate all parameter buckets instead.
|
|
392
|
+
//
|
|
393
|
+
// The fence is committed before the first delete of a compaction pass, and captured in the
|
|
394
|
+
// same snapshot as the checkpoint, so a checkpoint that could miss a deleted entry always
|
|
395
|
+
// observes the fence as well.
|
|
396
|
+
return {
|
|
397
|
+
invalidateParameterBuckets: true,
|
|
398
|
+
updatedParameterLookups: new Set()
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
// The query below runs at the checkpoint snapshot, which still sees entries deleted by a
|
|
402
|
+
// compaction pass that started after the snapshot.
|
|
403
|
+
return this.getParameterBucketChangesImpl({
|
|
404
|
+
lastCheckpoint: options.lastCheckpoint,
|
|
405
|
+
nextCheckpoint
|
|
406
|
+
});
|
|
359
407
|
}
|
|
360
408
|
checkpointChangesCache = new LRUCache({
|
|
361
409
|
max: 50,
|
|
362
410
|
maxSize: 12 * 1024 * 1024,
|
|
411
|
+
// When we have more fetches than the cache size, complete the fetches instead
|
|
412
|
+
// of failing with Error('evicted').
|
|
413
|
+
ignoreFetchAbort: true,
|
|
363
414
|
sizeCalculation: (value) => {
|
|
364
415
|
const paramSize = [...value.updatedParameterLookups].reduce((a, b) => a + b.length, 0);
|
|
365
416
|
const bucketSize = [...value.updatedDataBuckets].reduce((a, b) => a + b.length, 0);
|
|
@@ -371,7 +422,10 @@ export class MongoSyncBucketStorage extends BaseObserver {
|
|
|
371
422
|
}
|
|
372
423
|
});
|
|
373
424
|
async getCheckpointChanges(options) {
|
|
374
|
-
|
|
425
|
+
// The invalidation fence is part of the identity: the same checkpoint pair read before and
|
|
426
|
+
// after a compaction pass produces different results (specific lookups vs. invalidate-all).
|
|
427
|
+
const fence = requireMongoCheckpoint(options.nextCheckpoint).parameterChangesInvalidBefore;
|
|
428
|
+
const key = `${options.lastCheckpoint.checkpoint}_${options.lastCheckpoint.lsn}__${options.nextCheckpoint.checkpoint}_${options.nextCheckpoint.lsn}_${fence}`;
|
|
375
429
|
const result = await this.checkpointChangesCache.fetch(key, { context: { options } });
|
|
376
430
|
return result;
|
|
377
431
|
}
|
|
@@ -386,25 +440,44 @@ export class MongoSyncBucketStorage extends BaseObserver {
|
|
|
386
440
|
};
|
|
387
441
|
}
|
|
388
442
|
}
|
|
443
|
+
/**
|
|
444
|
+
* We don't support any other constructions of ReplicationCheckpoint.
|
|
445
|
+
*/
|
|
446
|
+
function requireMongoCheckpoint(checkpoint) {
|
|
447
|
+
if (!(checkpoint instanceof MongoReplicationCheckpoint)) {
|
|
448
|
+
throw new ServiceAssertionError(`Checkpoint changes require a checkpoint from getCheckpointInternal(), got ${checkpoint.constructor.name}`);
|
|
449
|
+
}
|
|
450
|
+
return checkpoint;
|
|
451
|
+
}
|
|
389
452
|
class MongoReplicationCheckpoint {
|
|
390
453
|
checkpoint;
|
|
391
454
|
lsn;
|
|
392
455
|
snapshotTime;
|
|
456
|
+
clusterTime;
|
|
457
|
+
parameterChangesInvalidBefore;
|
|
393
458
|
#storage;
|
|
394
|
-
constructor(storage, checkpoint, lsn, snapshotTime
|
|
459
|
+
constructor(storage, checkpoint, lsn, snapshotTime, clusterTime,
|
|
460
|
+
/** Captured in the same snapshot as the checkpoint. */
|
|
461
|
+
parameterChangesInvalidBefore) {
|
|
395
462
|
this.checkpoint = checkpoint;
|
|
396
463
|
this.lsn = lsn;
|
|
397
464
|
this.snapshotTime = snapshotTime;
|
|
465
|
+
this.clusterTime = clusterTime;
|
|
466
|
+
this.parameterChangesInvalidBefore = parameterChangesInvalidBefore;
|
|
398
467
|
this.#storage = storage;
|
|
399
468
|
}
|
|
400
469
|
async getParameterSets(lookups, limit) {
|
|
401
470
|
return this.#storage.getParameterSets(this, lookups, limit);
|
|
402
471
|
}
|
|
403
472
|
}
|
|
473
|
+
/**
|
|
474
|
+
* Used when no checkpoint has been persisted yet. This has no snapshot or invalidation fence, so
|
|
475
|
+
* it cannot be used for checkpoint change detection - see {@link requireMongoCheckpoint}.
|
|
476
|
+
*/
|
|
404
477
|
class EmptyReplicationCheckpoint {
|
|
405
478
|
checkpoint = 0n;
|
|
406
479
|
lsn = null;
|
|
407
|
-
async getParameterSets(_lookups) {
|
|
480
|
+
async getParameterSets(_lookups, _limit) {
|
|
408
481
|
return [];
|
|
409
482
|
}
|
|
410
483
|
}
|