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