@powersync/service-module-mongodb-storage 0.17.0 → 0.18.1
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 +27 -0
- package/dist/storage/MongoBucketStorage.d.ts +34 -16
- package/dist/storage/MongoBucketStorage.js +219 -70
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/implementation/MongoBucketBatch.d.ts +42 -23
- package/dist/storage/implementation/MongoBucketBatch.js +61 -44
- package/dist/storage/implementation/MongoBucketBatch.js.map +1 -1
- package/dist/storage/implementation/MongoChecksums.d.ts +10 -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 +2 -0
- 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 +123 -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 +41 -23
- package/dist/storage/implementation/MongoSyncBucketStorage.js +51 -43
- 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/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 +1 -2
- package/dist/storage/implementation/common/PersistedBatch.js +5 -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 +9 -14
- package/dist/storage/implementation/db.js.map +1 -1
- package/dist/storage/implementation/models.d.ts +4 -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 +42 -26
- 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/MongoSyncBucketStorageV1.d.ts +15 -17
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.js +47 -45
- package/dist/storage/implementation/v1/MongoSyncBucketStorageV1.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/MongoBucketBatchV3.d.ts +8 -4
- package/dist/storage/implementation/v3/MongoBucketBatchV3.js +286 -259
- 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 +19 -2
- 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 +40 -28
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js +232 -116
- package/dist/storage/implementation/v3/MongoSyncBucketStorageV3.js.map +1 -1
- package/dist/storage/implementation/v3/PersistedBatchV3.d.ts +1 -1
- 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 +13 -12
- package/dist/storage/implementation/v3/VersionedPowerSyncMongoV3.js +29 -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 +64 -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/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/storage/MongoBucketStorage.ts +334 -87
- package/src/storage/implementation/MongoBucketBatch.ts +86 -58
- package/src/storage/implementation/MongoChecksums.ts +6 -138
- package/src/storage/implementation/MongoCompactor.ts +19 -9
- 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 +154 -0
- package/src/storage/implementation/MongoStorageProvider.ts +5 -2
- package/src/storage/implementation/MongoSyncBucketStorage.ts +70 -56
- package/src/storage/implementation/MongoSyncRulesLock.ts +7 -4
- package/src/storage/implementation/common/MongoSyncBucketStorageCheckpoint.ts +7 -0
- package/src/storage/implementation/common/PersistedBatch.ts +7 -3
- package/src/storage/implementation/common/VersionedPowerSyncMongoBase.ts +1 -1
- package/src/storage/implementation/createMongoSyncBucketStorage.ts +21 -7
- package/src/storage/implementation/db.ts +11 -19
- package/src/storage/implementation/models.ts +4 -14
- package/src/storage/implementation/v1/MongoBucketBatchV1.ts +55 -34
- package/src/storage/implementation/v1/MongoChecksumsV1.ts +137 -4
- package/src/storage/implementation/v1/MongoSyncBucketStorageV1.ts +70 -64
- package/src/storage/implementation/v1/VersionedPowerSyncMongoV1.ts +11 -1
- package/src/storage/implementation/v1/models.ts +11 -1
- package/src/storage/implementation/v3/MongoBucketBatchV3.ts +358 -314
- package/src/storage/implementation/v3/MongoChecksumsV3.ts +262 -26
- package/src/storage/implementation/v3/MongoCompactorV3.ts +646 -29
- package/src/storage/implementation/v3/MongoStoppedSyncConfigCleanup.ts +480 -0
- package/src/storage/implementation/v3/MongoSyncBucketStorageV3.ts +315 -157
- package/src/storage/implementation/v3/PersistedBatchV3.ts +62 -36
- 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 +41 -36
- 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 +93 -55
- 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 +1077 -68
- package/test/src/storeCurrentData.test.ts +17 -7
- 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/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/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/v3/MongoParameterCompactorV3.ts +0 -24
- package/src/storage/implementation/v3/MongoParameterLookupV3.ts +0 -11
|
@@ -1,30 +1,48 @@
|
|
|
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 { BucketDefinitionMapping } from './implementation/BucketDefinitionMapping.js';
|
|
20
|
+
import { generateReplicationStreamName } from '../utils/util.js';
|
|
12
21
|
import type { MongoSyncBucketStorage } from './implementation/createMongoSyncBucketStorage.js';
|
|
13
22
|
import { createMongoSyncBucketStorage } from './implementation/createMongoSyncBucketStorage.js';
|
|
14
23
|
import { PowerSyncMongo } from './implementation/db.js';
|
|
15
24
|
import { getMongoStorageConfig, StorageConfig, SyncRuleDocumentBase } from './implementation/models.js';
|
|
16
25
|
import { MongoChecksumOptions } from './implementation/MongoChecksums.js';
|
|
17
|
-
import {
|
|
18
|
-
MongoPersistedSyncRulesContentV1,
|
|
19
|
-
MongoPersistedSyncRulesContentV3
|
|
20
|
-
} from './implementation/MongoPersistedSyncRulesContent.js';
|
|
26
|
+
import { MongoPersistedReplicationStream } from './implementation/MongoPersistedReplicationStream.js';
|
|
21
27
|
import { syncRuleStateUpdatePipeline } from './implementation/SyncRuleStateUpdate.js';
|
|
22
28
|
import { SyncRuleDocumentV1 } from './implementation/v1/models.js';
|
|
23
29
|
import { VersionedPowerSyncMongoV3 } from './implementation/v3/VersionedPowerSyncMongoV3.js';
|
|
24
|
-
import { ReplicationStreamDocumentV3, SyncConfigDefinition } from './storage-index.js';
|
|
30
|
+
import { ReplicationStreamDocumentV3, SyncConfigDefinition, SyncRuleConfigStateV3 } from './storage-index.js';
|
|
25
31
|
|
|
26
32
|
export interface MongoBucketStorageOptions {
|
|
27
|
-
|
|
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;
|
|
28
46
|
}
|
|
29
47
|
|
|
30
48
|
export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
@@ -32,8 +50,7 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
32
50
|
|
|
33
51
|
private readonly client: mongo.MongoClient;
|
|
34
52
|
private readonly session: mongo.ClientSession;
|
|
35
|
-
|
|
36
|
-
public readonly slot_name_prefix: string;
|
|
53
|
+
public readonly replicationStreamNamePrefix: string;
|
|
37
54
|
|
|
38
55
|
private activeStorageCache: MongoSyncBucketStorage | undefined;
|
|
39
56
|
|
|
@@ -41,51 +58,54 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
41
58
|
|
|
42
59
|
constructor(
|
|
43
60
|
db: PowerSyncMongo,
|
|
44
|
-
options:
|
|
45
|
-
slot_name_prefix: string;
|
|
46
|
-
},
|
|
47
|
-
private internalOptions?: MongoBucketStorageOptions
|
|
61
|
+
private options: MongoBucketStorageOptions
|
|
48
62
|
) {
|
|
49
63
|
super();
|
|
50
64
|
this.client = db.client;
|
|
51
65
|
this.db = db;
|
|
52
66
|
this.session = this.client.startSession();
|
|
53
|
-
this.
|
|
67
|
+
this.replicationStreamNamePrefix = options.replicationStreamNamePrefix;
|
|
54
68
|
}
|
|
55
69
|
|
|
56
70
|
async [Symbol.asyncDispose]() {
|
|
57
71
|
// No-op
|
|
58
72
|
}
|
|
59
73
|
|
|
60
|
-
getInstance(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
getInstance(
|
|
75
|
+
replicationStream: storage.PersistedReplicationStream,
|
|
76
|
+
options?: GetIntanceOptions
|
|
77
|
+
): MongoSyncBucketStorage {
|
|
78
|
+
if (!(replicationStream instanceof MongoPersistedReplicationStream)) {
|
|
79
|
+
throw new Error(`Expected MongoPersistedReplicationStream`);
|
|
64
80
|
}
|
|
65
|
-
|
|
66
|
-
|
|
81
|
+
let { replicationStreamId, replicationStreamName } = replicationStream;
|
|
82
|
+
if ((typeof replicationStreamId as any) == 'bigint') {
|
|
83
|
+
replicationStreamId = Number(replicationStreamId);
|
|
84
|
+
}
|
|
85
|
+
const storageConfig = replicationStream.getStorageConfig();
|
|
86
|
+
const syncRuleStorage = createMongoSyncBucketStorage(
|
|
67
87
|
this,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
88
|
+
replicationStreamId,
|
|
89
|
+
replicationStream,
|
|
90
|
+
replicationStreamName,
|
|
71
91
|
undefined,
|
|
72
92
|
{
|
|
73
|
-
|
|
93
|
+
checksumOptions: this.options.checksumOptions,
|
|
74
94
|
storageConfig
|
|
75
95
|
}
|
|
76
96
|
);
|
|
77
97
|
if (!options?.skipLifecycleHooks) {
|
|
78
|
-
this.iterateListeners((cb) => cb.syncStorageCreated?.(
|
|
98
|
+
this.iterateListeners((cb) => cb.syncStorageCreated?.(syncRuleStorage));
|
|
79
99
|
}
|
|
80
100
|
|
|
81
|
-
|
|
101
|
+
syncRuleStorage.registerListener({
|
|
82
102
|
batchStarted: (batch) => {
|
|
83
103
|
batch.registerListener({
|
|
84
104
|
replicationEvent: (payload) => this.iterateListeners((cb) => cb.replicationEvent?.(payload))
|
|
85
105
|
});
|
|
86
106
|
}
|
|
87
107
|
});
|
|
88
|
-
return
|
|
108
|
+
return syncRuleStorage;
|
|
89
109
|
}
|
|
90
110
|
|
|
91
111
|
async getSystemIdentifier(): Promise<storage.BucketStorageSystemIdentifier> {
|
|
@@ -105,25 +125,25 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
105
125
|
};
|
|
106
126
|
}
|
|
107
127
|
|
|
108
|
-
async restartReplication(
|
|
109
|
-
const next = await this.
|
|
110
|
-
const active = await this.
|
|
128
|
+
async restartReplication(replicationStreamId: number) {
|
|
129
|
+
const next = await this.getDeployingSyncConfig();
|
|
130
|
+
const active = await this.getActiveSyncConfig();
|
|
111
131
|
|
|
112
|
-
if (next != null && next.
|
|
132
|
+
if (next != null && next.content.replicationStreamId == replicationStreamId) {
|
|
113
133
|
// We need to redo the "next" replication stream
|
|
114
|
-
await this.updateSyncRules(next.asUpdateOptions());
|
|
134
|
+
await this.updateSyncRules(next.content.asUpdateOptions());
|
|
115
135
|
// Pro-actively stop replicating
|
|
116
136
|
await this.db.sync_rules.updateOne(
|
|
117
137
|
{
|
|
118
|
-
_id: next.
|
|
138
|
+
_id: next.content.replicationStreamId,
|
|
119
139
|
state: storage.SyncRuleState.PROCESSING
|
|
120
140
|
},
|
|
121
141
|
syncRuleStateUpdatePipeline(storage.SyncRuleState.STOP)
|
|
122
142
|
);
|
|
123
143
|
await this.db.notifyCheckpoint();
|
|
124
|
-
} else if (next == null && active?.
|
|
144
|
+
} else if (next == null && active?.content.replicationStreamId == replicationStreamId) {
|
|
125
145
|
// Slot removed for "active" replication stream, while there is no "next" one.
|
|
126
|
-
await this.updateSyncRules(active.asUpdateOptions());
|
|
146
|
+
await this.updateSyncRules(active.content.asUpdateOptions());
|
|
127
147
|
|
|
128
148
|
// In this case we keep the old one as active for clients, so that that existing clients
|
|
129
149
|
// can still get the latest data while we replicate the new ones.
|
|
@@ -131,18 +151,18 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
131
151
|
|
|
132
152
|
await this.db.sync_rules.updateOne(
|
|
133
153
|
{
|
|
134
|
-
_id: active.
|
|
154
|
+
_id: active.content.replicationStreamId,
|
|
135
155
|
state: storage.SyncRuleState.ACTIVE
|
|
136
156
|
},
|
|
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
|
},
|
|
148
168
|
syncRuleStateUpdatePipeline(storage.SyncRuleState.ERRORED)
|
|
@@ -155,13 +175,54 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
155
175
|
options: storage.UpdateSyncRulesOptions,
|
|
156
176
|
storageVersion: number,
|
|
157
177
|
storageConfig: StorageConfig
|
|
158
|
-
): Promise<
|
|
159
|
-
let rules:
|
|
178
|
+
): Promise<MongoPersistedReplicationStream> {
|
|
179
|
+
let rules: MongoPersistedReplicationStream | undefined = undefined;
|
|
160
180
|
const versioned = this.db.versioned(storageConfig) as VersionedPowerSyncMongoV3;
|
|
161
181
|
|
|
162
182
|
const session = this.session;
|
|
163
183
|
|
|
164
184
|
await session.withTransaction(async () => {
|
|
185
|
+
const active = await this.db.sync_rules.findOne<ReplicationStreamDocumentV3>(
|
|
186
|
+
{
|
|
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
|
+
|
|
165
226
|
// Only have a single replication stream with PROCESSING.
|
|
166
227
|
await this.db.sync_rules.updateMany(
|
|
167
228
|
{
|
|
@@ -188,9 +249,18 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
188
249
|
);
|
|
189
250
|
|
|
190
251
|
const id = Number(id_doc!.op_id);
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
const mapping =
|
|
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
|
+
);
|
|
194
264
|
|
|
195
265
|
const syncConfigDoc: SyncConfigDefinition = {
|
|
196
266
|
_id: new ObjectId(),
|
|
@@ -210,7 +280,6 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
210
280
|
{
|
|
211
281
|
_id: syncConfigDoc._id,
|
|
212
282
|
state: storage.SyncRuleState.PROCESSING,
|
|
213
|
-
keepalive_op: null,
|
|
214
283
|
last_checkpoint: null,
|
|
215
284
|
last_checkpoint_lsn: null,
|
|
216
285
|
no_checkpoint_before: null,
|
|
@@ -219,7 +288,7 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
219
288
|
],
|
|
220
289
|
snapshot_lsn: undefined,
|
|
221
290
|
state: storage.SyncRuleState.PROCESSING,
|
|
222
|
-
slot_name:
|
|
291
|
+
slot_name: replicationStreamName,
|
|
223
292
|
last_checkpoint_ts: null,
|
|
224
293
|
last_fatal_error: null,
|
|
225
294
|
last_fatal_error_ts: null,
|
|
@@ -227,20 +296,175 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
227
296
|
};
|
|
228
297
|
|
|
229
298
|
await this.db.sync_rules.insertOne(doc, { session });
|
|
230
|
-
|
|
231
|
-
rules = new MongoPersistedSyncRulesContentV3(this.db, doc, syncConfigDoc);
|
|
299
|
+
rules = new MongoPersistedReplicationStream(this.db, doc, [syncConfigDoc]);
|
|
232
300
|
if (options.lock) {
|
|
233
301
|
// The lock is persisted on rules.current_lock
|
|
234
302
|
await rules.lock(session);
|
|
235
303
|
}
|
|
236
304
|
});
|
|
237
305
|
|
|
306
|
+
// Notify only after the transaction has committed, so listeners cannot observe pre-commit state.
|
|
307
|
+
await this.db.notifyCheckpoint();
|
|
308
|
+
|
|
238
309
|
return rules!;
|
|
239
310
|
}
|
|
240
311
|
|
|
241
|
-
async
|
|
242
|
-
|
|
243
|
-
|
|
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
|
+
// The stream already exists, so an active replication job may already hold the stream lock.
|
|
462
|
+
// Deployment only persists the appended sync config; replication job locking is handled by
|
|
463
|
+
// the replicator.
|
|
464
|
+
return stream;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
async updateSyncRules(options: storage.UpdateSyncRulesOptions): Promise<MongoPersistedReplicationStream> {
|
|
244
468
|
const storageVersion =
|
|
245
469
|
options.storageVersion ?? options.config.parsed.config.storageVersion ?? storage.CURRENT_STORAGE_VERSION;
|
|
246
470
|
|
|
@@ -249,7 +473,7 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
249
473
|
return this.updateSyncRulesV3(options, storageVersion, storageConfig);
|
|
250
474
|
}
|
|
251
475
|
|
|
252
|
-
let rules:
|
|
476
|
+
let rules: MongoPersistedReplicationStream | undefined = undefined;
|
|
253
477
|
|
|
254
478
|
const session = this.session;
|
|
255
479
|
|
|
@@ -280,7 +504,7 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
280
504
|
);
|
|
281
505
|
|
|
282
506
|
const id = Number(id_doc!.op_id);
|
|
283
|
-
const slot_name =
|
|
507
|
+
const slot_name = generateReplicationStreamName(this.replicationStreamNamePrefix, id);
|
|
284
508
|
|
|
285
509
|
const doc: SyncRuleDocumentV1 = {
|
|
286
510
|
_id: id,
|
|
@@ -303,7 +527,7 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
303
527
|
|
|
304
528
|
await this.db.sync_rules.insertOne(doc, { session });
|
|
305
529
|
await this.db.notifyCheckpoint();
|
|
306
|
-
rules = new
|
|
530
|
+
rules = new MongoPersistedReplicationStream(this.db, doc);
|
|
307
531
|
if (options.lock) {
|
|
308
532
|
// The lock is persisted on rules.current_lock
|
|
309
533
|
await rules.lock(session);
|
|
@@ -313,9 +537,7 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
313
537
|
return rules!;
|
|
314
538
|
}
|
|
315
539
|
|
|
316
|
-
async
|
|
317
|
-
MongoPersistedSyncRulesContentV1 | MongoPersistedSyncRulesContentV3 | null
|
|
318
|
-
> {
|
|
540
|
+
async getActiveSyncConfig(): Promise<storage.ResolvedSyncConfig | null> {
|
|
319
541
|
const doc = await this.db.sync_rules.findOne(
|
|
320
542
|
{
|
|
321
543
|
state: { $in: [storage.SyncRuleState.ACTIVE, storage.SyncRuleState.ERRORED] }
|
|
@@ -323,10 +545,12 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
323
545
|
{ sort: { _id: -1 }, limit: 1 }
|
|
324
546
|
);
|
|
325
547
|
|
|
326
|
-
return this.
|
|
548
|
+
return this.resolvedSyncConfigFromDoc(doc, [storage.SyncRuleState.ACTIVE, storage.SyncRuleState.ERRORED], {
|
|
549
|
+
cacheActiveStorage: true
|
|
550
|
+
});
|
|
327
551
|
}
|
|
328
552
|
|
|
329
|
-
private async
|
|
553
|
+
private async replicationStreamFromDoc(doc: SyncRuleDocumentBase | null, stateFilter: storage.SyncRuleState[]) {
|
|
330
554
|
if (doc == null) {
|
|
331
555
|
return null;
|
|
332
556
|
}
|
|
@@ -334,8 +558,8 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
334
558
|
|
|
335
559
|
if (storageConfig.incrementalReprocessing) {
|
|
336
560
|
const v3 = doc as ReplicationStreamDocumentV3;
|
|
337
|
-
const
|
|
338
|
-
if (
|
|
561
|
+
const matching = v3.sync_configs.filter((c) => stateFilter.includes(c.state));
|
|
562
|
+
if (matching.length == 0) {
|
|
339
563
|
return null;
|
|
340
564
|
}
|
|
341
565
|
|
|
@@ -343,28 +567,33 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
343
567
|
// that checks for active replication streams.
|
|
344
568
|
// It is not a major bottleneck though, since it only runs once every couple of seconds at most.
|
|
345
569
|
const db = this.db.versioned(storageConfig) as VersionedPowerSyncMongoV3;
|
|
346
|
-
const
|
|
347
|
-
|
|
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) {
|
|
348
577
|
return null;
|
|
349
578
|
}
|
|
350
|
-
return new
|
|
579
|
+
return new MongoPersistedReplicationStream(this.db, v3, syncConfigDocs);
|
|
351
580
|
}
|
|
352
581
|
|
|
353
|
-
return new
|
|
582
|
+
return new MongoPersistedReplicationStream(this.db, doc as SyncRuleDocumentV1);
|
|
354
583
|
}
|
|
355
584
|
|
|
356
|
-
async
|
|
585
|
+
async getDeployingSyncConfig(): Promise<storage.ResolvedSyncConfig | null> {
|
|
357
586
|
const doc = await this.db.sync_rules.findOne(
|
|
358
587
|
{
|
|
359
|
-
state: storage.SyncRuleState.PROCESSING
|
|
588
|
+
$or: [{ state: storage.SyncRuleState.PROCESSING }, { 'sync_configs.state': storage.SyncRuleState.PROCESSING }]
|
|
360
589
|
},
|
|
361
590
|
{ sort: { _id: -1 }, limit: 1 }
|
|
362
591
|
);
|
|
363
592
|
|
|
364
|
-
return this.
|
|
593
|
+
return this.resolvedSyncConfigFromDoc(doc, [storage.SyncRuleState.PROCESSING]);
|
|
365
594
|
}
|
|
366
595
|
|
|
367
|
-
async
|
|
596
|
+
async getReplicatingReplicationStreams(): Promise<storage.PersistedReplicationStream[]> {
|
|
368
597
|
const docs = await this.db.sync_rules
|
|
369
598
|
.find({
|
|
370
599
|
state: { $in: [storage.SyncRuleState.PROCESSING, storage.SyncRuleState.ACTIVE] }
|
|
@@ -374,13 +603,13 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
374
603
|
return (
|
|
375
604
|
await Promise.all(
|
|
376
605
|
docs.map((doc) => {
|
|
377
|
-
return this.
|
|
606
|
+
return this.replicationStreamFromDoc(doc, [storage.SyncRuleState.PROCESSING, storage.SyncRuleState.ACTIVE]);
|
|
378
607
|
})
|
|
379
608
|
)
|
|
380
609
|
).filter((r) => r != null);
|
|
381
610
|
}
|
|
382
611
|
|
|
383
|
-
async
|
|
612
|
+
async getStoppedReplicationStreams(): Promise<storage.PersistedReplicationStream[]> {
|
|
384
613
|
const docs = await this.db.sync_rules
|
|
385
614
|
.find({
|
|
386
615
|
state: storage.SyncRuleState.STOP
|
|
@@ -390,28 +619,46 @@ export class MongoBucketStorage extends storage.BucketStorageFactory {
|
|
|
390
619
|
return (
|
|
391
620
|
await Promise.all(
|
|
392
621
|
docs.map((doc) => {
|
|
393
|
-
return this.
|
|
622
|
+
return this.replicationStreamFromDoc(doc, [storage.SyncRuleState.STOP]);
|
|
394
623
|
})
|
|
395
624
|
)
|
|
396
625
|
).filter((d) => d != null);
|
|
397
626
|
}
|
|
398
627
|
|
|
399
|
-
async
|
|
400
|
-
|
|
401
|
-
|
|
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) {
|
|
402
635
|
return null;
|
|
403
636
|
}
|
|
404
637
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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
|
+
};
|
|
415
662
|
}
|
|
416
663
|
|
|
417
664
|
async getStorageMetrics(): Promise<storage.StorageMetrics> {
|