@powersync/service-module-mongodb-storage 0.0.0-dev-20260602073133 → 0.0.0-dev-20260803144812
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 +101 -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 +41 -16
- package/dist/storage/MongoBucketStorage.js +226 -71
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoBucketBatch.d.ts +56 -25
- package/dist/storage/implementation/MongoBucketBatch.js +110 -62
- 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 +17 -19
- package/dist/storage/implementation/MongoCompactor.js +80 -263
- 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 +7 -6
- package/dist/storage/implementation/MongoParameterCompactor.js +25 -2
- package/dist/storage/implementation/MongoParameterCompactor.js.map +1 -1
- package/dist/storage/implementation/MongoParsedSyncConfigSet.d.ts +13 -0
- package/dist/storage/implementation/MongoParsedSyncConfigSet.js +64 -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 +123 -0
- package/dist/storage/implementation/MongoPersistedSyncConfigContent.js.map +1 -0
- package/dist/storage/implementation/MongoStorageProvider.js +39 -4
- package/dist/storage/implementation/MongoStorageProvider.js.map +1 -1
- package/dist/storage/implementation/MongoSyncBucketStorage.d.ts +57 -29
- package/dist/storage/implementation/MongoSyncBucketStorage.js +87 -61
- package/dist/storage/implementation/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.d.ts +1 -1
- package/dist/storage/implementation/MongoSyncRulesLock.js +3 -3
- package/dist/storage/implementation/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/implementation/MongoWriteCheckpointAPI.d.ts +2 -1
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js +171 -24
- package/dist/storage/implementation/MongoWriteCheckpointAPI.js.map +1 -1
- package/dist/storage/implementation/common/MongoSyncBucketStorageCheckpoint.d.ts +8 -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 +7 -2
- package/dist/storage/implementation/common/PersistedBatch.js +12 -0
- 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.js +17 -15
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/models.d.ts +20 -13
- package/dist/storage/implementation/models.js.map +1 -1
- package/dist/storage/implementation/v1/MongoBucketBatchV1.d.ts +9 -1
- package/dist/storage/implementation/v1/MongoBucketBatchV1.js +61 -29
- 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 +11 -2
- package/dist/storage/implementation/v1/MongoCompactorV1.js +251 -2
- package/dist/storage/implementation/v1/MongoCompactorV1.js.map +1 -1
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.d.ts +18 -19
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +82 -58
- 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/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/MongoBucketBatchV3.d.ts +8 -4
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js +309 -259
- 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 +40 -2
- package/dist/storage/implementation/v3/MongoCompactorV3.js +647 -23
- package/dist/storage/implementation/v3/MongoCompactorV3.js.map +1 -1
- package/dist/storage/implementation/v3/MongoStoppedSyncConfigCleanup.d.ts +67 -0
- package/dist/storage/implementation/v3/MongoStoppedSyncConfigCleanup.js +351 -0
- package/dist/storage/implementation/v3/MongoStoppedSyncConfigCleanup.js.map +1 -0
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.d.ts +45 -30
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +272 -140
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -1
- package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +6 -3
- package/dist/storage/implementation/v3/PersistedBatchV3.js +84 -21
- 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 +15 -13
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js +32 -27
- 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 +77 -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/models.d.ts +101 -21
- 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 +21 -0
- package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.js +44 -0
- package/dist/storage/implementation/v3/object-storage/BucketDataObjectStorage.js.map +1 -0
- package/dist/storage/implementation/v3/object-storage/ObjectStorage.d.ts +30 -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 +70 -0
- package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.js +146 -0
- package/dist/storage/implementation/v3/object-storage/ObjectStorageLifecycle.js.map +1 -0
- package/dist/storage/implementation/v3/object-storage/S3ObjectStorage.d.ts +42 -0
- package/dist/storage/implementation/v3/object-storage/S3ObjectStorage.js +285 -0
- package/dist/storage/implementation/v3/object-storage/S3ObjectStorage.js.map +1 -0
- package/dist/storage/implementation/v3/source-table-utils.d.ts +55 -0
- package/dist/storage/implementation/v3/source-table-utils.js +214 -0
- package/dist/storage/implementation/v3/source-table-utils.js.map +1 -0
- package/dist/storage/storage-index.d.ts +4 -4
- package/dist/storage/storage-index.js +4 -4
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/types/types.d.ts +49 -3
- package/dist/types/types.js +48 -1
- 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 +128 -4
- package/dist/utils/util.js.map +1 -1
- package/package.json +12 -19
- package/src/migrations/db/migrations/1782950400000-checkpoint-requested-at-index.ts +55 -0
- package/src/storage/MongoBucketStorage.ts +347 -88
- package/src/storage/implementation/MongoBucketBatch.ts +147 -82
- package/src/storage/implementation/MongoChecksums.ts +93 -153
- package/src/storage/implementation/MongoCompactor.ts +102 -316
- package/src/storage/implementation/MongoHydrationState.ts +61 -0
- package/src/storage/implementation/MongoParameterCompactor.ts +25 -6
- package/src/storage/implementation/MongoParsedSyncConfigSet.ts +88 -0
- package/src/storage/implementation/MongoPersistedReplicationStream.ts +118 -0
- package/src/storage/implementation/MongoPersistedSyncConfigContent.ts +154 -0
- package/src/storage/implementation/MongoStorageProvider.ts +46 -4
- package/src/storage/implementation/MongoSyncBucketStorage.ts +121 -87
- package/src/storage/implementation/MongoSyncRulesLock.ts +7 -4
- package/src/storage/implementation/MongoWriteCheckpointAPI.ts +202 -28
- package/src/storage/implementation/common/MongoSyncBucketStorageCheckpoint.ts +9 -0
- package/src/storage/implementation/common/PersistedBatch.ts +19 -3
- package/src/storage/implementation/common/VersionedPowerSyncMongoBase.ts +1 -1
- package/src/storage/implementation/createMongoSyncBucketStorage.ts +21 -7
- package/src/storage/implementation/db.ts +19 -20
- package/src/storage/implementation/models.ts +20 -14
- package/src/storage/implementation/v1/MongoBucketBatchV1.ts +75 -37
- package/src/storage/implementation/v1/MongoChecksumsV1.ts +154 -12
- package/src/storage/implementation/v1/MongoCompactorV1.ts +294 -9
- package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +142 -105
- 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 +11 -1
- package/src/storage/implementation/v3/BucketDataContextV3.ts +32 -0
- package/src/storage/implementation/v3/MongoBucketBatchV3.ts +382 -321
- package/src/storage/implementation/v3/MongoChecksumsV3.ts +250 -32
- package/src/storage/implementation/v3/MongoCompactorV3.ts +847 -32
- package/src/storage/implementation/v3/MongoStoppedSyncConfigCleanup.ts +482 -0
- package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +359 -187
- package/src/storage/implementation/v3/PersistedBatchV3.ts +118 -37
- package/src/storage/implementation/v3/SourceRecordStoreV3.ts +12 -12
- package/src/storage/implementation/v3/VersionedPowerSyncMongoV3.ts +46 -36
- package/src/storage/implementation/v3/bucket-format.ts +97 -0
- package/src/storage/implementation/v3/chunking.ts +40 -0
- package/src/storage/implementation/v3/models.ts +132 -55
- package/src/storage/implementation/v3/object-storage/BucketDataObjectStorage.ts +54 -0
- package/src/storage/implementation/v3/object-storage/ObjectStorage.ts +29 -0
- package/src/storage/implementation/v3/object-storage/ObjectStorageLifecycle.ts +171 -0
- package/src/storage/implementation/v3/object-storage/S3ObjectStorage.ts +343 -0
- package/src/storage/implementation/v3/source-table-utils.ts +392 -0
- package/src/storage/storage-index.ts +12 -4
- package/src/types/types.ts +58 -1
- package/src/utils/test-utils.ts +8 -3
- package/src/utils/util.ts +185 -6
- package/test/src/__snapshots__/storage.test.ts.snap +0 -75
- package/test/src/__snapshots__/storage_sync.test.ts.snap +35 -617
- package/test/src/cleanup-stopped-sync-configs.test.ts +671 -0
- package/test/src/helpers/MemoryObjectStorage.ts +53 -0
- package/test/src/helpers/s3TestFactory.ts +69 -0
- package/test/src/object_storage_lifecycle.test.ts +59 -0
- package/test/src/setup.ts +6 -1
- package/test/src/storage.test.ts +227 -13
- package/test/src/storage_compacting.test.ts +1951 -12
- package/test/src/storage_object_storage_inline_threshold.test.ts +116 -0
- package/test/src/storage_s3_checksums.test.ts +191 -0
- package/test/src/storage_s3_compaction_lifecycle.test.ts +417 -0
- package/test/src/storage_s3_reading.test.ts +526 -0
- package/test/src/storage_s3_writing.test.ts +135 -0
- package/test/src/storage_sync.test.ts +1180 -73
- package/test/src/storeCurrentData.test.ts +227 -0
- package/test/src/util.ts +2 -1
- 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/MongoParameterCompactorV3.d.ts +0 -9
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.js +0 -18
- package/dist/storage/implementation/v3/MongoParameterCompactorV3.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/MongoParameterCompactorV3.ts +0 -24
- package/src/storage/implementation/v3/MongoParameterLookupV3.ts +0 -11
- package/src/storage/implementation/v3/SingleBucketStoreV3.ts +0 -68
|
@@ -1,30 +1,55 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
GetIntanceOptions,
|
|
3
|
+
LEGACY_STORAGE_VERSION,
|
|
4
|
+
SingleSyncConfigBucketDefinitionMapping,
|
|
5
|
+
storage
|
|
6
|
+
} from '@powersync/service-core';
|
|
2
7
|
|
|
3
|
-
import { DO_NOT_LOG, ErrorCode, ServiceError } from '@powersync/lib-services-framework';
|
|
8
|
+
import { DO_NOT_LOG, ErrorCode, logger, ServiceError } from '@powersync/lib-services-framework';
|
|
4
9
|
import { v4 as uuid } from 'uuid';
|
|
5
10
|
|
|
6
11
|
import * as lib_mongo from '@powersync/lib-service-mongodb';
|
|
7
12
|
import { mongo } from '@powersync/lib-service-mongodb';
|
|
8
13
|
|
|
14
|
+
import {
|
|
15
|
+
describeIncrementalSyncConfigUpdate,
|
|
16
|
+
formatIncrementalSyncConfigUpdateLog,
|
|
17
|
+
isCompatible
|
|
18
|
+
} from '@powersync/service-core';
|
|
9
19
|
import { ObjectId } from 'bson';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
20
|
+
import { DEFAULT_CLEAR_BATCH_THROTTLE_RATE } from '../types/types.js';
|
|
21
|
+
import { generateReplicationStreamName } from '../utils/util.js';
|
|
12
22
|
import type { MongoSyncBucketStorage } from './implementation/createMongoSyncBucketStorage.js';
|
|
13
23
|
import { createMongoSyncBucketStorage } from './implementation/createMongoSyncBucketStorage.js';
|
|
14
24
|
import { PowerSyncMongo } from './implementation/db.js';
|
|
15
25
|
import { getMongoStorageConfig, StorageConfig, SyncRuleDocumentBase } from './implementation/models.js';
|
|
16
26
|
import { MongoChecksumOptions } from './implementation/MongoChecksums.js';
|
|
17
|
-
import {
|
|
18
|
-
MongoPersistedSyncRulesContentV1,
|
|
19
|
-
MongoPersistedSyncRulesContentV3
|
|
20
|
-
} from './implementation/MongoPersistedSyncRulesContent.js';
|
|
27
|
+
import { MongoPersistedReplicationStream } from './implementation/MongoPersistedReplicationStream.js';
|
|
21
28
|
import { syncRuleStateUpdatePipeline } from './implementation/SyncRuleStateUpdate.js';
|
|
22
29
|
import { SyncRuleDocumentV1 } from './implementation/v1/models.js';
|
|
30
|
+
import { ObjectStorage } from './implementation/v3/object-storage/ObjectStorage.js';
|
|
23
31
|
import { VersionedPowerSyncMongoV3 } from './implementation/v3/VersionedPowerSyncMongoV3.js';
|
|
24
|
-
import { ReplicationStreamDocumentV3, SyncConfigDefinition } from './storage-index.js';
|
|
32
|
+
import { ReplicationStreamDocumentV3, SyncConfigDefinition, SyncRuleConfigStateV3 } from './storage-index.js';
|
|
25
33
|
|
|
26
34
|
export interface MongoBucketStorageOptions {
|
|
27
|
-
checksumOptions?: Omit<MongoChecksumOptions, 'storageConfig'
|
|
35
|
+
checksumOptions?: Omit<MongoChecksumOptions, 'storageConfig'>;
|
|
36
|
+
objectStorage?: ObjectStorage;
|
|
37
|
+
inlineThresholdBytes?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Prefix for replication stream name and Postgres logical replication slot name.
|
|
40
|
+
*/
|
|
41
|
+
replicationStreamNamePrefix: string;
|
|
42
|
+
readPreference?: mongo.ReadPreference;
|
|
43
|
+
checksumCacheTtlMs?: number;
|
|
44
|
+
clearBatchThrottleRate?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Reuse a compatible active replication stream by appending a new sync config.
|
|
47
|
+
*
|
|
48
|
+
* This currently requires source replication support. MongoDB sources can process multiple
|
|
49
|
+
* sync configs in one replication stream, but other source connectors still expect a single
|
|
50
|
+
* sync config per stream.
|
|
51
|
+
*/
|
|
52
|
+
supportsMultipleSyncConfigs?: boolean;
|
|
28
53
|
}
|
|
29
54
|
|
|
30
55
|
export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
@@ -32,8 +57,7 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
32
57
|
|
|
33
58
|
private readonly client: mongo.MongoClient;
|
|
34
59
|
private readonly session: mongo.ClientSession;
|
|
35
|
-
|
|
36
|
-
public readonly slot_name_prefix: string;
|
|
60
|
+
public readonly replicationStreamNamePrefix: string;
|
|
37
61
|
|
|
38
62
|
private activeStorageCache: MongoSyncBucketStorage | undefined;
|
|
39
63
|
|
|
@@ -41,51 +65,59 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
41
65
|
|
|
42
66
|
constructor(
|
|
43
67
|
db: PowerSyncMongo,
|
|
44
|
-
options:
|
|
45
|
-
slot_name_prefix: string;
|
|
46
|
-
},
|
|
47
|
-
private internalOptions?: MongoBucketStorageOptions
|
|
68
|
+
private options: MongoBucketStorageOptions
|
|
48
69
|
) {
|
|
49
70
|
super();
|
|
50
71
|
this.client = db.client;
|
|
51
72
|
this.db = db;
|
|
52
73
|
this.session = this.client.startSession();
|
|
53
|
-
this.
|
|
74
|
+
this.replicationStreamNamePrefix = options.replicationStreamNamePrefix;
|
|
54
75
|
}
|
|
55
76
|
|
|
56
77
|
async [Symbol.asyncDispose]() {
|
|
57
78
|
// No-op
|
|
58
79
|
}
|
|
59
80
|
|
|
60
|
-
getInstance(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
81
|
+
getInstance(
|
|
82
|
+
replicationStream: storage.PersistedReplicationStream,
|
|
83
|
+
options?: GetIntanceOptions
|
|
84
|
+
): MongoSyncBucketStorage {
|
|
85
|
+
if (!(replicationStream instanceof MongoPersistedReplicationStream)) {
|
|
86
|
+
throw new Error(`Expected MongoPersistedReplicationStream`);
|
|
64
87
|
}
|
|
65
|
-
|
|
66
|
-
|
|
88
|
+
let { replicationStreamId, replicationStreamName } = replicationStream;
|
|
89
|
+
if ((typeof replicationStreamId as any) == 'bigint') {
|
|
90
|
+
replicationStreamId = Number(replicationStreamId);
|
|
91
|
+
}
|
|
92
|
+
const storageConfig = replicationStream.getStorageConfig();
|
|
93
|
+
const syncRuleStorage = createMongoSyncBucketStorage(
|
|
67
94
|
this,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
95
|
+
replicationStreamId,
|
|
96
|
+
replicationStream,
|
|
97
|
+
replicationStreamName,
|
|
71
98
|
undefined,
|
|
72
99
|
{
|
|
73
|
-
|
|
74
|
-
|
|
100
|
+
checksumOptions: this.options.checksumOptions,
|
|
101
|
+
readPreference: this.options.readPreference,
|
|
102
|
+
checksumCacheTtlMs: this.options.checksumCacheTtlMs,
|
|
103
|
+
storageConfig,
|
|
104
|
+
objectStorage: this.options.objectStorage,
|
|
105
|
+
inlineThresholdBytes: this.options.inlineThresholdBytes,
|
|
106
|
+
clearBatchThrottleRate: this.options.clearBatchThrottleRate ?? DEFAULT_CLEAR_BATCH_THROTTLE_RATE
|
|
75
107
|
}
|
|
76
108
|
);
|
|
77
109
|
if (!options?.skipLifecycleHooks) {
|
|
78
|
-
this.iterateListeners((cb) => cb.syncStorageCreated?.(
|
|
110
|
+
this.iterateListeners((cb) => cb.syncStorageCreated?.(syncRuleStorage));
|
|
79
111
|
}
|
|
80
112
|
|
|
81
|
-
|
|
113
|
+
syncRuleStorage.registerListener({
|
|
82
114
|
batchStarted: (batch) => {
|
|
83
115
|
batch.registerListener({
|
|
84
116
|
replicationEvent: (payload) => this.iterateListeners((cb) => cb.replicationEvent?.(payload))
|
|
85
117
|
});
|
|
86
118
|
}
|
|
87
119
|
});
|
|
88
|
-
return
|
|
120
|
+
return syncRuleStorage;
|
|
89
121
|
}
|
|
90
122
|
|
|
91
123
|
async getSystemIdentifier(): Promise<storage.BucketStorageSystemIdentifier> {
|
|
@@ -105,25 +137,25 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
105
137
|
};
|
|
106
138
|
}
|
|
107
139
|
|
|
108
|
-
async restartReplication(
|
|
109
|
-
const next = await this.
|
|
110
|
-
const active = await this.
|
|
140
|
+
async restartReplication(replicationStreamId: number) {
|
|
141
|
+
const next = await this.getDeployingSyncConfig();
|
|
142
|
+
const active = await this.getActiveSyncConfig();
|
|
111
143
|
|
|
112
|
-
if (next != null && next.
|
|
144
|
+
if (next != null && next.content.replicationStreamId == replicationStreamId) {
|
|
113
145
|
// We need to redo the "next" replication stream
|
|
114
|
-
await this.updateSyncRules(next.asUpdateOptions());
|
|
146
|
+
await this.updateSyncRules(next.content.asUpdateOptions());
|
|
115
147
|
// Pro-actively stop replicating
|
|
116
148
|
await this.db.sync_rules.updateOne(
|
|
117
149
|
{
|
|
118
|
-
_id: next.
|
|
150
|
+
_id: next.content.replicationStreamId,
|
|
119
151
|
state: storage.SyncRuleState.PROCESSING
|
|
120
152
|
},
|
|
121
153
|
syncRuleStateUpdatePipeline(storage.SyncRuleState.STOP)
|
|
122
154
|
);
|
|
123
155
|
await this.db.notifyCheckpoint();
|
|
124
|
-
} else if (next == null && active?.
|
|
156
|
+
} else if (next == null && active?.content.replicationStreamId == replicationStreamId) {
|
|
125
157
|
// Slot removed for "active" replication stream, while there is no "next" one.
|
|
126
|
-
await this.updateSyncRules(active.asUpdateOptions());
|
|
158
|
+
await this.updateSyncRules(active.content.asUpdateOptions());
|
|
127
159
|
|
|
128
160
|
// In this case we keep the old one as active for clients, so that that existing clients
|
|
129
161
|
// can still get the latest data while we replicate the new ones.
|
|
@@ -131,18 +163,18 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
131
163
|
|
|
132
164
|
await this.db.sync_rules.updateOne(
|
|
133
165
|
{
|
|
134
|
-
_id: active.
|
|
166
|
+
_id: active.content.replicationStreamId,
|
|
135
167
|
state: storage.SyncRuleState.ACTIVE
|
|
136
168
|
},
|
|
137
169
|
syncRuleStateUpdatePipeline(storage.SyncRuleState.ERRORED)
|
|
138
170
|
);
|
|
139
171
|
await this.db.notifyCheckpoint();
|
|
140
|
-
} else if (next != null && active?.
|
|
172
|
+
} else if (next != null && active?.content.replicationStreamId == replicationStreamId) {
|
|
141
173
|
// Already have next replication stream, but need to stop replicating the active one.
|
|
142
174
|
|
|
143
175
|
await this.db.sync_rules.updateOne(
|
|
144
176
|
{
|
|
145
|
-
_id: active.
|
|
177
|
+
_id: active.content.replicationStreamId,
|
|
146
178
|
state: storage.SyncRuleState.ACTIVE
|
|
147
179
|
},
|
|
148
180
|
syncRuleStateUpdatePipeline(storage.SyncRuleState.ERRORED)
|
|
@@ -155,13 +187,54 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
155
187
|
options: storage.UpdateSyncRulesOptions,
|
|
156
188
|
storageVersion: number,
|
|
157
189
|
storageConfig: StorageConfig
|
|
158
|
-
): Promise<
|
|
159
|
-
let rules:
|
|
190
|
+
): Promise<MongoPersistedReplicationStream> {
|
|
191
|
+
let rules: MongoPersistedReplicationStream | undefined = undefined;
|
|
160
192
|
const versioned = this.db.versioned(storageConfig) as VersionedPowerSyncMongoV3;
|
|
161
193
|
|
|
162
194
|
const session = this.session;
|
|
163
195
|
|
|
164
196
|
await session.withTransaction(async () => {
|
|
197
|
+
const active = await this.db.sync_rules.findOne<ReplicationStreamDocumentV3>(
|
|
198
|
+
{
|
|
199
|
+
state: storage.SyncRuleState.ACTIVE,
|
|
200
|
+
storage_version: storageVersion
|
|
201
|
+
},
|
|
202
|
+
{ session, sort: { _id: -1 }, limit: 1 }
|
|
203
|
+
);
|
|
204
|
+
if (active != null) {
|
|
205
|
+
const existingConfigDocs = await this.loadSyncConfigDefinitions(versioned, active, session);
|
|
206
|
+
|
|
207
|
+
if (
|
|
208
|
+
this.options.supportsMultipleSyncConfigs &&
|
|
209
|
+
isCompatible(
|
|
210
|
+
existingConfigDocs.map((d) => d.serialized_plan ?? null),
|
|
211
|
+
options.config,
|
|
212
|
+
logger
|
|
213
|
+
)
|
|
214
|
+
) {
|
|
215
|
+
logger.info(`Using incremental reprocessing`);
|
|
216
|
+
await this.db.sync_rules.updateMany(
|
|
217
|
+
{
|
|
218
|
+
state: storage.SyncRuleState.PROCESSING
|
|
219
|
+
},
|
|
220
|
+
syncRuleStateUpdatePipeline(storage.SyncRuleState.STOP),
|
|
221
|
+
{ session }
|
|
222
|
+
);
|
|
223
|
+
await this.stopEmbeddedDeployingConfigs(active, session);
|
|
224
|
+
rules = await this.appendSyncConfigToStream({
|
|
225
|
+
versioned,
|
|
226
|
+
existing: active,
|
|
227
|
+
existingConfigDocs,
|
|
228
|
+
options,
|
|
229
|
+
storageVersion,
|
|
230
|
+
session
|
|
231
|
+
});
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
await this.stopEmbeddedDeployingConfigs(active, session);
|
|
236
|
+
}
|
|
237
|
+
|
|
165
238
|
// Only have a single replication stream with PROCESSING.
|
|
166
239
|
await this.db.sync_rules.updateMany(
|
|
167
240
|
{
|
|
@@ -188,9 +261,18 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
188
261
|
);
|
|
189
262
|
|
|
190
263
|
const id = Number(id_doc!.op_id);
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
const mapping =
|
|
264
|
+
const replicationStreamName = generateReplicationStreamName(this.replicationStreamNamePrefix, id);
|
|
265
|
+
|
|
266
|
+
const mapping =
|
|
267
|
+
options.config.plan == null
|
|
268
|
+
? // For legacy sync rules and streams, use the parsed config directly to create a mapping
|
|
269
|
+
SingleSyncConfigBucketDefinitionMapping.fromParsedSyncConfig(options.config.parsed)
|
|
270
|
+
: // For new sync streams, always use the serialized version
|
|
271
|
+
SingleSyncConfigBucketDefinitionMapping.constructIncrementalMappingFromSerializedPlans(
|
|
272
|
+
[],
|
|
273
|
+
options.config.plan.plan,
|
|
274
|
+
[]
|
|
275
|
+
);
|
|
194
276
|
|
|
195
277
|
const syncConfigDoc: SyncConfigDefinition = {
|
|
196
278
|
_id: new ObjectId(),
|
|
@@ -210,7 +292,6 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
210
292
|
{
|
|
211
293
|
_id: syncConfigDoc._id,
|
|
212
294
|
state: storage.SyncRuleState.PROCESSING,
|
|
213
|
-
keepalive_op: null,
|
|
214
295
|
last_checkpoint: null,
|
|
215
296
|
last_checkpoint_lsn: null,
|
|
216
297
|
no_checkpoint_before: null,
|
|
@@ -219,7 +300,7 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
219
300
|
],
|
|
220
301
|
snapshot_lsn: undefined,
|
|
221
302
|
state: storage.SyncRuleState.PROCESSING,
|
|
222
|
-
slot_name:
|
|
303
|
+
slot_name: replicationStreamName,
|
|
223
304
|
last_checkpoint_ts: null,
|
|
224
305
|
last_fatal_error: null,
|
|
225
306
|
last_fatal_error_ts: null,
|
|
@@ -227,20 +308,175 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
227
308
|
};
|
|
228
309
|
|
|
229
310
|
await this.db.sync_rules.insertOne(doc, { session });
|
|
230
|
-
|
|
231
|
-
rules = new MongoPersistedSyncRulesContentV3(this.db, doc, syncConfigDoc);
|
|
311
|
+
rules = new MongoPersistedReplicationStream(this.db, doc, [syncConfigDoc]);
|
|
232
312
|
if (options.lock) {
|
|
233
313
|
// The lock is persisted on rules.current_lock
|
|
234
314
|
await rules.lock(session);
|
|
235
315
|
}
|
|
236
316
|
});
|
|
237
317
|
|
|
318
|
+
// Notify only after the transaction has committed, so listeners cannot observe pre-commit state.
|
|
319
|
+
await this.db.notifyCheckpoint();
|
|
320
|
+
|
|
238
321
|
return rules!;
|
|
239
322
|
}
|
|
240
323
|
|
|
241
|
-
async
|
|
242
|
-
|
|
243
|
-
|
|
324
|
+
private async loadSyncConfigDefinitions(
|
|
325
|
+
versioned: VersionedPowerSyncMongoV3,
|
|
326
|
+
existing: ReplicationStreamDocumentV3,
|
|
327
|
+
session: mongo.ClientSession
|
|
328
|
+
) {
|
|
329
|
+
const activeConfigIds = existing.sync_configs
|
|
330
|
+
.filter((config) => config.state == storage.SyncRuleState.ACTIVE)
|
|
331
|
+
.map((config) => config._id);
|
|
332
|
+
|
|
333
|
+
return versioned.syncConfigDefinitions
|
|
334
|
+
.find(
|
|
335
|
+
{
|
|
336
|
+
_id: { $in: activeConfigIds }
|
|
337
|
+
},
|
|
338
|
+
{ session }
|
|
339
|
+
)
|
|
340
|
+
.toArray();
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Load _all_ definition mappings for a replication stream - used as a base to generate new ids.
|
|
345
|
+
*/
|
|
346
|
+
private async loadHistoricalSyncConfigRuleMappings(
|
|
347
|
+
versioned: VersionedPowerSyncMongoV3,
|
|
348
|
+
replicationStreamId: number,
|
|
349
|
+
session: mongo.ClientSession
|
|
350
|
+
) {
|
|
351
|
+
return versioned.syncConfigDefinitions
|
|
352
|
+
.find(
|
|
353
|
+
{
|
|
354
|
+
replication_stream_id: replicationStreamId
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
session,
|
|
358
|
+
projection: {
|
|
359
|
+
rule_mapping: 1
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
)
|
|
363
|
+
.toArray();
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
private async stopEmbeddedDeployingConfigs(existing: ReplicationStreamDocumentV3, session: mongo.ClientSession) {
|
|
367
|
+
const deployingConfigs = existing.sync_configs
|
|
368
|
+
.filter((config) => config.state == storage.SyncRuleState.PROCESSING)
|
|
369
|
+
.map((config) => config._id);
|
|
370
|
+
if (deployingConfigs.length == 0) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
await this.db.sync_rules.updateOne(
|
|
375
|
+
{
|
|
376
|
+
_id: existing._id,
|
|
377
|
+
'sync_configs._id': { $in: deployingConfigs }
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
$set: {
|
|
381
|
+
'sync_configs.$[config].state': storage.SyncRuleState.STOP
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
session,
|
|
386
|
+
arrayFilters: [{ 'config._id': { $in: deployingConfigs } }]
|
|
387
|
+
}
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
private logIncrementalDefinitionChanges(changes: ReturnType<typeof describeIncrementalSyncConfigUpdate>) {
|
|
392
|
+
logger.info(`Incremental reprocessing sync config update:\n${formatIncrementalSyncConfigUpdateLog(changes)}`);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
private async appendSyncConfigToStream(options: {
|
|
396
|
+
versioned: VersionedPowerSyncMongoV3;
|
|
397
|
+
existing: ReplicationStreamDocumentV3;
|
|
398
|
+
existingConfigDocs: SyncConfigDefinition[];
|
|
399
|
+
options: storage.UpdateSyncRulesOptions;
|
|
400
|
+
storageVersion: number;
|
|
401
|
+
session: mongo.ClientSession;
|
|
402
|
+
}): Promise<MongoPersistedReplicationStream> {
|
|
403
|
+
const { versioned, existing, existingConfigDocs, options: updateOptions, storageVersion, session } = options;
|
|
404
|
+
const compatibleConfigs = existingConfigDocs.map((doc) => ({
|
|
405
|
+
plan: doc.serialized_plan!.plan,
|
|
406
|
+
mapping: SingleSyncConfigBucketDefinitionMapping.fromPersistedMapping(doc.rule_mapping)
|
|
407
|
+
}));
|
|
408
|
+
const historicalRuleMappings = await this.loadHistoricalSyncConfigRuleMappings(versioned, existing._id, session);
|
|
409
|
+
const reservedMappings = historicalRuleMappings.map((doc) =>
|
|
410
|
+
SingleSyncConfigBucketDefinitionMapping.fromPersistedMapping(doc.rule_mapping)
|
|
411
|
+
);
|
|
412
|
+
const mappingResult = SingleSyncConfigBucketDefinitionMapping.constructIncrementalMappingWithChanges(
|
|
413
|
+
compatibleConfigs,
|
|
414
|
+
updateOptions.config.plan!.plan,
|
|
415
|
+
reservedMappings
|
|
416
|
+
);
|
|
417
|
+
const mapping = mappingResult.mapping;
|
|
418
|
+
this.logIncrementalDefinitionChanges(
|
|
419
|
+
describeIncrementalSyncConfigUpdate({
|
|
420
|
+
activeMappings: existingConfigDocs.map((doc) =>
|
|
421
|
+
SingleSyncConfigBucketDefinitionMapping.fromPersistedMapping(doc.rule_mapping)
|
|
422
|
+
),
|
|
423
|
+
newMapping: mapping,
|
|
424
|
+
newSyncConfig: updateOptions.config.parsed,
|
|
425
|
+
mappingChanges: mappingResult.changes
|
|
426
|
+
})
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
const syncConfigDoc: SyncConfigDefinition = {
|
|
430
|
+
_id: new ObjectId(),
|
|
431
|
+
replication_stream_id: existing._id,
|
|
432
|
+
created_at: new Date(),
|
|
433
|
+
storage_version: storageVersion,
|
|
434
|
+
content: updateOptions.config.yaml,
|
|
435
|
+
serialized_plan: updateOptions.config.plan,
|
|
436
|
+
rule_mapping: mapping.serialize()
|
|
437
|
+
};
|
|
438
|
+
await versioned.syncConfigDefinitions.insertOne(syncConfigDoc, { session });
|
|
439
|
+
const syncConfigState: SyncRuleConfigStateV3 = {
|
|
440
|
+
_id: syncConfigDoc._id,
|
|
441
|
+
state: storage.SyncRuleState.PROCESSING,
|
|
442
|
+
last_checkpoint: null,
|
|
443
|
+
last_checkpoint_lsn: null,
|
|
444
|
+
no_checkpoint_before: null,
|
|
445
|
+
snapshot_done: false
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
await this.db.sync_rules.updateOne(
|
|
449
|
+
{ _id: existing._id },
|
|
450
|
+
{
|
|
451
|
+
$push: {
|
|
452
|
+
sync_configs: syncConfigState
|
|
453
|
+
},
|
|
454
|
+
$set: {
|
|
455
|
+
last_fatal_error: null,
|
|
456
|
+
last_fatal_error_ts: null
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
{ session }
|
|
460
|
+
);
|
|
461
|
+
const syncConfigStates = [
|
|
462
|
+
...existing.sync_configs.filter((config) => config.state == storage.SyncRuleState.ACTIVE),
|
|
463
|
+
syncConfigState
|
|
464
|
+
];
|
|
465
|
+
const stream = new MongoPersistedReplicationStream(
|
|
466
|
+
this.db,
|
|
467
|
+
{
|
|
468
|
+
...existing,
|
|
469
|
+
sync_configs: syncConfigStates
|
|
470
|
+
},
|
|
471
|
+
[...existingConfigDocs, syncConfigDoc]
|
|
472
|
+
);
|
|
473
|
+
// The stream already exists, so an active replication job may already hold the stream lock.
|
|
474
|
+
// Deployment only persists the appended sync config; replication job locking is handled by
|
|
475
|
+
// the replicator.
|
|
476
|
+
return stream;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
async updateSyncRules(options: storage.UpdateSyncRulesOptions): Promise<MongoPersistedReplicationStream> {
|
|
244
480
|
const storageVersion =
|
|
245
481
|
options.storageVersion ?? options.config.parsed.config.storageVersion ?? storage.CURRENT_STORAGE_VERSION;
|
|
246
482
|
|
|
@@ -249,7 +485,7 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
249
485
|
return this.updateSyncRulesV3(options, storageVersion, storageConfig);
|
|
250
486
|
}
|
|
251
487
|
|
|
252
|
-
let rules:
|
|
488
|
+
let rules: MongoPersistedReplicationStream | undefined = undefined;
|
|
253
489
|
|
|
254
490
|
const session = this.session;
|
|
255
491
|
|
|
@@ -280,7 +516,7 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
280
516
|
);
|
|
281
517
|
|
|
282
518
|
const id = Number(id_doc!.op_id);
|
|
283
|
-
const slot_name =
|
|
519
|
+
const slot_name = generateReplicationStreamName(this.replicationStreamNamePrefix, id);
|
|
284
520
|
|
|
285
521
|
const doc: SyncRuleDocumentV1 = {
|
|
286
522
|
_id: id,
|
|
@@ -303,7 +539,7 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
303
539
|
|
|
304
540
|
await this.db.sync_rules.insertOne(doc, { session });
|
|
305
541
|
await this.db.notifyCheckpoint();
|
|
306
|
-
rules = new
|
|
542
|
+
rules = new MongoPersistedReplicationStream(this.db, doc);
|
|
307
543
|
if (options.lock) {
|
|
308
544
|
// The lock is persisted on rules.current_lock
|
|
309
545
|
await rules.lock(session);
|
|
@@ -313,9 +549,7 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
313
549
|
return rules!;
|
|
314
550
|
}
|
|
315
551
|
|
|
316
|
-
async
|
|
317
|
-
MongoPersistedSyncRulesContentV1 | MongoPersistedSyncRulesContentV3 | null
|
|
318
|
-
> {
|
|
552
|
+
async getActiveSyncConfig(): Promise<storage.ResolvedSyncConfig | null> {
|
|
319
553
|
const doc = await this.db.sync_rules.findOne(
|
|
320
554
|
{
|
|
321
555
|
state: { $in: [storage.SyncRuleState.ACTIVE, storage.SyncRuleState.ERRORED] }
|
|
@@ -323,10 +557,12 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
323
557
|
{ sort: { _id: -1 }, limit: 1 }
|
|
324
558
|
);
|
|
325
559
|
|
|
326
|
-
return this.
|
|
560
|
+
return this.resolvedSyncConfigFromDoc(doc, [storage.SyncRuleState.ACTIVE, storage.SyncRuleState.ERRORED], {
|
|
561
|
+
cacheActiveStorage: true
|
|
562
|
+
});
|
|
327
563
|
}
|
|
328
564
|
|
|
329
|
-
private async
|
|
565
|
+
private async replicationStreamFromDoc(doc: SyncRuleDocumentBase | null, stateFilter: storage.SyncRuleState[]) {
|
|
330
566
|
if (doc == null) {
|
|
331
567
|
return null;
|
|
332
568
|
}
|
|
@@ -334,8 +570,8 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
334
570
|
|
|
335
571
|
if (storageConfig.incrementalReprocessing) {
|
|
336
572
|
const v3 = doc as ReplicationStreamDocumentV3;
|
|
337
|
-
const
|
|
338
|
-
if (
|
|
573
|
+
const matching = v3.sync_configs.filter((c) => stateFilter.includes(c.state));
|
|
574
|
+
if (matching.length == 0) {
|
|
339
575
|
return null;
|
|
340
576
|
}
|
|
341
577
|
|
|
@@ -343,28 +579,33 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
343
579
|
// that checks for active replication streams.
|
|
344
580
|
// It is not a major bottleneck though, since it only runs once every couple of seconds at most.
|
|
345
581
|
const db = this.db.versioned(storageConfig) as VersionedPowerSyncMongoV3;
|
|
346
|
-
const
|
|
347
|
-
|
|
582
|
+
const syncConfigDocs = await db.syncConfigDefinitions
|
|
583
|
+
.find({
|
|
584
|
+
_id: { $in: matching.map((config) => config._id) }
|
|
585
|
+
})
|
|
586
|
+
.toArray();
|
|
587
|
+
|
|
588
|
+
if (syncConfigDocs.length == 0) {
|
|
348
589
|
return null;
|
|
349
590
|
}
|
|
350
|
-
return new
|
|
591
|
+
return new MongoPersistedReplicationStream(this.db, v3, syncConfigDocs);
|
|
351
592
|
}
|
|
352
593
|
|
|
353
|
-
return new
|
|
594
|
+
return new MongoPersistedReplicationStream(this.db, doc as SyncRuleDocumentV1);
|
|
354
595
|
}
|
|
355
596
|
|
|
356
|
-
async
|
|
597
|
+
async getDeployingSyncConfig(): Promise<storage.ResolvedSyncConfig | null> {
|
|
357
598
|
const doc = await this.db.sync_rules.findOne(
|
|
358
599
|
{
|
|
359
|
-
state: storage.SyncRuleState.PROCESSING
|
|
600
|
+
$or: [{ state: storage.SyncRuleState.PROCESSING }, { 'sync_configs.state': storage.SyncRuleState.PROCESSING }]
|
|
360
601
|
},
|
|
361
602
|
{ sort: { _id: -1 }, limit: 1 }
|
|
362
603
|
);
|
|
363
604
|
|
|
364
|
-
return this.
|
|
605
|
+
return this.resolvedSyncConfigFromDoc(doc, [storage.SyncRuleState.PROCESSING]);
|
|
365
606
|
}
|
|
366
607
|
|
|
367
|
-
async
|
|
608
|
+
async getReplicatingReplicationStreams(): Promise<storage.PersistedReplicationStream[]> {
|
|
368
609
|
const docs = await this.db.sync_rules
|
|
369
610
|
.find({
|
|
370
611
|
state: { $in: [storage.SyncRuleState.PROCESSING, storage.SyncRuleState.ACTIVE] }
|
|
@@ -374,13 +615,13 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
374
615
|
return (
|
|
375
616
|
await Promise.all(
|
|
376
617
|
docs.map((doc) => {
|
|
377
|
-
return this.
|
|
618
|
+
return this.replicationStreamFromDoc(doc, [storage.SyncRuleState.PROCESSING, storage.SyncRuleState.ACTIVE]);
|
|
378
619
|
})
|
|
379
620
|
)
|
|
380
621
|
).filter((r) => r != null);
|
|
381
622
|
}
|
|
382
623
|
|
|
383
|
-
async
|
|
624
|
+
async getStoppedReplicationStreams(): Promise<storage.PersistedReplicationStream[]> {
|
|
384
625
|
const docs = await this.db.sync_rules
|
|
385
626
|
.find({
|
|
386
627
|
state: storage.SyncRuleState.STOP
|
|
@@ -390,28 +631,46 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
390
631
|
return (
|
|
391
632
|
await Promise.all(
|
|
392
633
|
docs.map((doc) => {
|
|
393
|
-
return this.
|
|
634
|
+
return this.replicationStreamFromDoc(doc, [storage.SyncRuleState.STOP]);
|
|
394
635
|
})
|
|
395
636
|
)
|
|
396
637
|
).filter((d) => d != null);
|
|
397
638
|
}
|
|
398
639
|
|
|
399
|
-
async
|
|
400
|
-
|
|
401
|
-
|
|
640
|
+
private async resolvedSyncConfigFromDoc(
|
|
641
|
+
doc: SyncRuleDocumentBase | null,
|
|
642
|
+
stateFilter: storage.SyncRuleState[],
|
|
643
|
+
options: { cacheActiveStorage?: boolean } = {}
|
|
644
|
+
): Promise<storage.ResolvedSyncConfig | null> {
|
|
645
|
+
const stream = await this.replicationStreamFromDoc(doc, stateFilter);
|
|
646
|
+
if (stream == null) {
|
|
402
647
|
return null;
|
|
403
648
|
}
|
|
404
649
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
650
|
+
const content = stream.syncConfigContent[0];
|
|
651
|
+
const thisFactory = this;
|
|
652
|
+
|
|
653
|
+
return {
|
|
654
|
+
content,
|
|
655
|
+
replicationStream: stream,
|
|
656
|
+
get storage() {
|
|
657
|
+
// It is important that this instance is cached.
|
|
658
|
+
// Not for the instance construction itself, but to ensure that internal caches on the instance
|
|
659
|
+
// are re-used properly.
|
|
660
|
+
if (
|
|
661
|
+
options.cacheActiveStorage &&
|
|
662
|
+
thisFactory.activeStorageCache?.replicationStream.replicationJobId == stream.replicationJobId
|
|
663
|
+
) {
|
|
664
|
+
return thisFactory.activeStorageCache;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const instance = thisFactory.getInstance(stream);
|
|
668
|
+
if (options.cacheActiveStorage) {
|
|
669
|
+
thisFactory.activeStorageCache = instance;
|
|
670
|
+
}
|
|
671
|
+
return instance;
|
|
672
|
+
}
|
|
673
|
+
};
|
|
415
674
|
}
|
|
416
675
|
|
|
417
676
|
async getStorageMetrics(): Promise<storage.StorageMetrics> {
|