@powersync/service-core 1.22.0 → 1.23.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 +17 -0
- package/dist/api/RouteAPI.d.ts +2 -2
- package/dist/api/diagnostics.d.ts +12 -1
- package/dist/api/diagnostics.js +34 -22
- package/dist/api/diagnostics.js.map +1 -1
- package/dist/entry/commands/compact-action.js +1 -1
- package/dist/entry/commands/compact-action.js.map +1 -1
- package/dist/modules/AbstractModule.d.ts +6 -2
- package/dist/modules/AbstractModule.js.map +1 -1
- package/dist/replication/AbstractReplicator.d.ts +2 -2
- package/dist/replication/AbstractReplicator.js +24 -23
- package/dist/replication/AbstractReplicator.js.map +1 -1
- package/dist/replication/ReplicationModule.d.ts +3 -3
- package/dist/replication/ReplicationModule.js.map +1 -1
- package/dist/routes/configure-fastify.d.ts +12 -12
- package/dist/routes/endpoints/admin.d.ts +24 -24
- package/dist/routes/endpoints/admin.js +44 -34
- package/dist/routes/endpoints/admin.js.map +1 -1
- package/dist/routes/endpoints/checkpointing.js +1 -1
- package/dist/routes/endpoints/checkpointing.js.map +1 -1
- package/dist/routes/endpoints/socket-route.js +1 -1
- package/dist/routes/endpoints/socket-route.js.map +1 -1
- package/dist/routes/endpoints/sync-rules.js +22 -13
- package/dist/routes/endpoints/sync-rules.js.map +1 -1
- package/dist/routes/endpoints/sync-stream.js +1 -1
- package/dist/routes/endpoints/sync-stream.js.map +1 -1
- package/dist/runner/teardown.js +8 -8
- package/dist/runner/teardown.js.map +1 -1
- package/dist/storage/BucketStorageBatch.d.ts +0 -6
- package/dist/storage/BucketStorageBatch.js.map +1 -1
- package/dist/storage/BucketStorageFactory.d.ts +22 -27
- package/dist/storage/BucketStorageFactory.js +4 -18
- package/dist/storage/BucketStorageFactory.js.map +1 -1
- package/dist/storage/ParsedSyncConfigSet.d.ts +23 -0
- package/dist/storage/ParsedSyncConfigSet.js +2 -0
- package/dist/storage/ParsedSyncConfigSet.js.map +1 -0
- package/dist/storage/PersistedReplicationStream.d.ts +32 -0
- package/dist/storage/PersistedReplicationStream.js +26 -0
- package/dist/storage/PersistedReplicationStream.js.map +1 -0
- package/dist/storage/PersistedSyncConfigContent.d.ts +60 -0
- package/dist/storage/PersistedSyncConfigContent.js +123 -0
- package/dist/storage/PersistedSyncConfigContent.js.map +1 -0
- package/dist/storage/PersistedSyncConfigStatus.d.ts +13 -0
- package/dist/storage/PersistedSyncConfigStatus.js +2 -0
- package/dist/storage/PersistedSyncConfigStatus.js.map +1 -0
- package/dist/storage/SourceTable.d.ts +9 -3
- package/dist/storage/SourceTable.js +13 -3
- package/dist/storage/SourceTable.js.map +1 -1
- package/dist/storage/SyncRulesBucketStorage.d.ts +59 -16
- package/dist/storage/SyncRulesBucketStorage.js.map +1 -1
- package/dist/storage/implementation/BucketDefinitionMapping.d.ts +117 -0
- package/dist/storage/implementation/BucketDefinitionMapping.js +277 -0
- package/dist/storage/implementation/BucketDefinitionMapping.js.map +1 -0
- package/dist/storage/implementation/IncrementalReprocessingCompatibility.d.ts +6 -0
- package/dist/storage/implementation/IncrementalReprocessingCompatibility.js +31 -0
- package/dist/storage/implementation/IncrementalReprocessingCompatibility.js.map +1 -0
- package/dist/storage/implementation/IncrementalReprocessingSyncConfigLog.d.ts +17 -0
- package/dist/storage/implementation/IncrementalReprocessingSyncConfigLog.js +62 -0
- package/dist/storage/implementation/IncrementalReprocessingSyncConfigLog.js.map +1 -0
- package/dist/storage/implementation/ReplicationStreamStorageIds.d.ts +15 -0
- package/dist/storage/implementation/ReplicationStreamStorageIds.js +20 -0
- package/dist/storage/implementation/ReplicationStreamStorageIds.js.map +1 -0
- package/dist/storage/storage-index.d.ts +8 -1
- package/dist/storage/storage-index.js +8 -1
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/sync/sync.js +5 -0
- package/dist/sync/sync.js.map +1 -1
- package/dist/util/checkpointing.js +1 -1
- package/dist/util/checkpointing.js.map +1 -1
- package/dist/util/config/types.d.ts +1 -1
- package/dist/util/lsn.d.ts +4 -0
- package/dist/util/lsn.js +10 -0
- package/dist/util/lsn.js.map +1 -1
- package/package.json +6 -7
- package/src/api/RouteAPI.ts +2 -2
- package/src/api/diagnostics.ts +43 -26
- package/src/entry/commands/compact-action.ts +1 -1
- package/src/modules/AbstractModule.ts +6 -2
- package/src/replication/AbstractReplicator.ts +27 -26
- package/src/replication/ReplicationModule.ts +2 -3
- package/src/routes/endpoints/admin.ts +70 -49
- package/src/routes/endpoints/checkpointing.ts +1 -1
- package/src/routes/endpoints/socket-route.ts +1 -1
- package/src/routes/endpoints/sync-rules.ts +23 -13
- package/src/routes/endpoints/sync-stream.ts +1 -1
- package/src/runner/teardown.ts +8 -8
- package/src/storage/BucketStorageBatch.ts +0 -7
- package/src/storage/BucketStorageFactory.ts +30 -39
- package/src/storage/ParsedSyncConfigSet.ts +25 -0
- package/src/storage/PersistedReplicationStream.ts +55 -0
- package/src/storage/PersistedSyncConfigContent.ts +188 -0
- package/src/storage/PersistedSyncConfigStatus.ts +14 -0
- package/src/storage/SourceTable.ts +20 -3
- package/src/storage/SyncRulesBucketStorage.ts +64 -16
- package/src/storage/implementation/BucketDefinitionMapping.ts +436 -0
- package/src/storage/implementation/IncrementalReprocessingCompatibility.ts +41 -0
- package/src/storage/implementation/IncrementalReprocessingSyncConfigLog.ts +109 -0
- package/src/storage/implementation/ReplicationStreamStorageIds.ts +21 -0
- package/src/storage/storage-index.ts +9 -1
- package/src/sync/sync.ts +5 -0
- package/src/util/checkpointing.ts +1 -1
- package/src/util/config/types.ts +1 -1
- package/src/util/lsn.ts +9 -0
- package/test/src/diagnostics.test.ts +61 -34
- package/test/src/module-loader.test.ts +33 -1
- package/test/src/routes/admin.test.ts +180 -18
- package/test/src/routes/mocks.ts +6 -2
- package/tsconfig.json +1 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/storage/PersistedSyncRulesContent.d.ts +0 -59
- package/dist/storage/PersistedSyncRulesContent.js +0 -100
- package/dist/storage/PersistedSyncRulesContent.js.map +0 -1
- package/src/storage/PersistedSyncRulesContent.ts +0 -174
package/dist/runner/teardown.js
CHANGED
|
@@ -35,20 +35,20 @@ async function terminateSyncRules(storageFactory, moduleManager) {
|
|
|
35
35
|
const locks = [];
|
|
36
36
|
while (Date.now() - start < 120_000) {
|
|
37
37
|
let retry = false;
|
|
38
|
-
const
|
|
38
|
+
const replicatingStreams = await storageFactory.getReplicatingReplicationStreams();
|
|
39
39
|
// Lock all the replicating replication streams
|
|
40
|
-
for (const
|
|
41
|
-
const lock = await
|
|
40
|
+
for (const replicatingStream of replicatingStreams) {
|
|
41
|
+
const lock = await replicatingStream.lock();
|
|
42
42
|
locks.push(lock);
|
|
43
43
|
}
|
|
44
|
-
const
|
|
45
|
-
const
|
|
44
|
+
const stoppedStreams = await storageFactory.getStoppedReplicationStreams();
|
|
45
|
+
const combinedStreams = [...replicatingStreams, ...stoppedStreams];
|
|
46
46
|
try {
|
|
47
47
|
// Clean up any module specific configuration for the replication stream
|
|
48
|
-
await moduleManager.tearDown({ syncRules:
|
|
48
|
+
await moduleManager.tearDown({ replicationStreams: combinedStreams, syncRules: combinedStreams });
|
|
49
49
|
// Mark the replication stream as terminated
|
|
50
|
-
for (let
|
|
51
|
-
const syncRulesStorage = storageFactory.getInstance(
|
|
50
|
+
for (let replicationStream of combinedStreams) {
|
|
51
|
+
const syncRulesStorage = storageFactory.getInstance(replicationStream);
|
|
52
52
|
// The storage will be dropped at the end of the teardown, so we don't need to clear it here
|
|
53
53
|
await syncRulesStorage.terminate({ clearStorage: false });
|
|
54
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"teardown.js","sourceRoot":"","sources":["../../src/runner/teardown.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,eAAe;AACf,mFAAmF;AACnF,wBAAwB;AAExB,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,KAAK,OAAO,MAAM,6BAA6B,CAAC;AAEvD,OAAO,KAAK,MAAM,MAAM,2BAA2B,CAAC;AACpD,OAAO,KAAK,KAAK,MAAM,uBAAuB,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,YAAgC;IAC7D,IAAI,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;QACpD,MAAM,cAAc,GAAG,IAAI,MAAM,CAAC,uBAAuB,CAAC;YACxD,WAAW,EAAE,MAAM,CAAC,kBAAkB,CAAC,QAAQ;YAC/C,aAAa,EAAE,MAAM;SACtB,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG,SAAS,CAAC,iBAAiB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,aAAa,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAC/C,0DAA0D;QAC1D,MAAM,cAAc,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAE7C,MAAM,kBAAkB,CAAC,cAAc,CAAC,aAAa,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;QAC1F,MAAM,cAAc,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;QAC5D,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,cAA4C,EAAE,aAAoC;IAClH,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,KAAK,GAA8B,EAAE,CAAC;IAC5C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,OAAO,EAAE,CAAC;QACpC,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,MAAM,
|
|
1
|
+
{"version":3,"file":"teardown.js","sourceRoot":"","sources":["../../src/runner/teardown.ts"],"names":[],"mappings":"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"}
|
|
@@ -68,10 +68,6 @@ export interface BucketStorageBatch extends ObserverClient<BucketBatchStorageLis
|
|
|
68
68
|
* PostgreSQL logical replication slots.
|
|
69
69
|
*/
|
|
70
70
|
setResumeLsn(lsn: string): Promise<void>;
|
|
71
|
-
/**
|
|
72
|
-
* Get the last checkpoint LSN, from either commit or keepalive.
|
|
73
|
-
*/
|
|
74
|
-
lastCheckpointLsn: string | null;
|
|
75
71
|
/**
|
|
76
72
|
* LSN to resume from.
|
|
77
73
|
*
|
|
@@ -181,8 +177,6 @@ export interface CheckpointResult {
|
|
|
181
177
|
/**
|
|
182
178
|
* True if a checkpoint was actually created by this operation. This can be false even if checkpointBlocked is false,
|
|
183
179
|
* if the checkpoint was empty.
|
|
184
|
-
*
|
|
185
|
-
* This is primarily used for testing.
|
|
186
180
|
*/
|
|
187
181
|
checkpointCreated: boolean;
|
|
188
182
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BucketStorageBatch.js","sourceRoot":"","sources":["../../src/storage/BucketStorageBatch.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,mCAAmC,GAAqC;IACnF,sBAAsB,EAAE,IAAI;IAC5B,uBAAuB,EAAE,IAAI;CAC9B,CAAC;
|
|
1
|
+
{"version":3,"file":"BucketStorageBatch.js","sourceRoot":"","sources":["../../src/storage/BucketStorageBatch.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,mCAAmC,GAAqC;IACnF,sBAAsB,EAAE,IAAI;IAC5B,uBAAuB,EAAE,IAAI;CAC9B,CAAC;AAkJF,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,qCAAiB,CAAA;IACjB,qCAAiB,CAAA;IACjB,qCAAiB,CAAA;AACnB,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { BaseObserver } from '@powersync/lib-services-framework';
|
|
2
|
-
import { SerializedCompatibilityContext, SyncConfigWithErrors } from '@powersync/service-sync-rules';
|
|
2
|
+
import { SerializedCompatibilityContext, SerializedSyncPlanV1, SyncConfigWithErrors } from '@powersync/service-sync-rules';
|
|
3
3
|
import { ReplicationError } from '@powersync/service-types';
|
|
4
|
-
import {
|
|
4
|
+
import { PersistedReplicationStream } from './PersistedReplicationStream.js';
|
|
5
|
+
import { PersistedSyncConfigContent } from './PersistedSyncConfigContent.js';
|
|
5
6
|
import { ReplicationEventPayload } from './ReplicationEventPayload.js';
|
|
6
7
|
import { ReplicationLock } from './ReplicationLock.js';
|
|
7
8
|
import { ReportStorage } from './ReportStorage.js';
|
|
@@ -20,17 +21,17 @@ export declare abstract class BucketStorageFactory extends BaseObserver<BucketSt
|
|
|
20
21
|
*/
|
|
21
22
|
configureSyncRules(options: UpdateSyncRulesOptions): Promise<{
|
|
22
23
|
updated: boolean;
|
|
23
|
-
persisted_sync_rules?:
|
|
24
|
+
persisted_sync_rules?: PersistedReplicationStream;
|
|
24
25
|
lock?: ReplicationLock;
|
|
25
26
|
}>;
|
|
26
27
|
/**
|
|
27
28
|
* Get a storage instance to query sync data for specific sync config.
|
|
28
29
|
*/
|
|
29
|
-
abstract getInstance(
|
|
30
|
+
abstract getInstance(replicationStream: PersistedReplicationStream, options?: GetIntanceOptions): SyncRulesBucketStorage;
|
|
30
31
|
/**
|
|
31
32
|
* Deploy new sync config.
|
|
32
33
|
*/
|
|
33
|
-
abstract updateSyncRules(options: UpdateSyncRulesOptions): Promise<
|
|
34
|
+
abstract updateSyncRules(options: UpdateSyncRulesOptions): Promise<PersistedReplicationStream>;
|
|
34
35
|
/**
|
|
35
36
|
* Indicate that a slot was removed, and we should re-sync by creating
|
|
36
37
|
* a new replication stream.
|
|
@@ -41,35 +42,23 @@ export declare abstract class BucketStorageFactory extends BaseObserver<BucketSt
|
|
|
41
42
|
*
|
|
42
43
|
* Replication should be restarted after this.
|
|
43
44
|
*/
|
|
44
|
-
abstract restartReplication(
|
|
45
|
+
abstract restartReplication(replicationStreamId: number): Promise<void>;
|
|
45
46
|
/**
|
|
46
|
-
* Get the sync config used for querying.
|
|
47
|
+
* Get the sync config and storage used for querying.
|
|
47
48
|
*/
|
|
48
|
-
|
|
49
|
+
abstract getActiveSyncConfig(): Promise<ResolvedSyncConfig | null>;
|
|
49
50
|
/**
|
|
50
|
-
* Get the sync config
|
|
51
|
+
* Get the sync config and storage that is still deploying.
|
|
51
52
|
*/
|
|
52
|
-
abstract
|
|
53
|
+
abstract getDeployingSyncConfig(): Promise<ResolvedSyncConfig | null>;
|
|
53
54
|
/**
|
|
54
|
-
* Get
|
|
55
|
+
* Get all replication streams currently replicating.
|
|
55
56
|
*/
|
|
56
|
-
|
|
57
|
+
abstract getReplicatingReplicationStreams(): Promise<PersistedReplicationStream[]>;
|
|
57
58
|
/**
|
|
58
|
-
* Get
|
|
59
|
+
* Get all replication streams stopped but not terminated yet.
|
|
59
60
|
*/
|
|
60
|
-
abstract
|
|
61
|
-
/**
|
|
62
|
-
* Get all sync config currently replicating. Typically this is the "active" and "next" sync config.
|
|
63
|
-
*/
|
|
64
|
-
abstract getReplicatingSyncRules(): Promise<PersistedSyncRulesContent[]>;
|
|
65
|
-
/**
|
|
66
|
-
* Get all sync config stopped but not terminated yet.
|
|
67
|
-
*/
|
|
68
|
-
abstract getStoppedSyncRules(): Promise<PersistedSyncRulesContent[]>;
|
|
69
|
-
/**
|
|
70
|
-
* Get the active storage instance.
|
|
71
|
-
*/
|
|
72
|
-
abstract getActiveStorage(): Promise<SyncRulesBucketStorage | null>;
|
|
61
|
+
abstract getStoppedReplicationStreams(): Promise<PersistedReplicationStream[]>;
|
|
73
62
|
/**
|
|
74
63
|
* Get storage size of active replication stream.
|
|
75
64
|
*/
|
|
@@ -88,6 +77,11 @@ export interface BucketStorageFactoryListener {
|
|
|
88
77
|
syncStorageCreated: (storage: SyncRulesBucketStorage) => void;
|
|
89
78
|
replicationEvent: (event: ReplicationEventPayload) => void;
|
|
90
79
|
}
|
|
80
|
+
export interface ResolvedSyncConfig {
|
|
81
|
+
content: PersistedSyncConfigContent;
|
|
82
|
+
replicationStream: PersistedReplicationStream;
|
|
83
|
+
storage: SyncRulesBucketStorage;
|
|
84
|
+
}
|
|
91
85
|
export interface StorageMetrics {
|
|
92
86
|
/**
|
|
93
87
|
* Size of operations (bucket_data)
|
|
@@ -129,7 +123,7 @@ export interface SerializedSyncPlan {
|
|
|
129
123
|
/**
|
|
130
124
|
* The serialized plan, from {@link serializeSyncPlan}.
|
|
131
125
|
*/
|
|
132
|
-
plan:
|
|
126
|
+
plan: SerializedSyncPlanV1;
|
|
133
127
|
compatibility: SerializedCompatibilityContext;
|
|
134
128
|
/**
|
|
135
129
|
* Event descriptors are not currently represented in the sync plan because they don't use the sync streams compiler
|
|
@@ -188,4 +182,5 @@ export interface TestStorageConfig {
|
|
|
188
182
|
factory: TestStorageFactory;
|
|
189
183
|
tableIdStrings: boolean;
|
|
190
184
|
storageVersion?: number;
|
|
185
|
+
compressedBucketStorage?: boolean;
|
|
191
186
|
}
|
|
@@ -14,13 +14,13 @@ export class BucketStorageFactory extends BaseObserver {
|
|
|
14
14
|
* Update sync config from configuration, if changed.
|
|
15
15
|
*/
|
|
16
16
|
async configureSyncRules(options) {
|
|
17
|
-
const
|
|
18
|
-
const active = await this.
|
|
19
|
-
if (
|
|
17
|
+
const deploying = await this.getDeployingSyncConfig();
|
|
18
|
+
const active = await this.getActiveSyncConfig();
|
|
19
|
+
if (deploying?.content.sync_rules_content == options.config.yaml) {
|
|
20
20
|
logger.info('Sync config unchanged');
|
|
21
21
|
return { updated: false };
|
|
22
22
|
}
|
|
23
|
-
else if (
|
|
23
|
+
else if (deploying == null && active?.content.sync_rules_content == options.config.yaml) {
|
|
24
24
|
logger.info('Sync config unchanged');
|
|
25
25
|
return { updated: false };
|
|
26
26
|
}
|
|
@@ -30,20 +30,6 @@ export class BucketStorageFactory extends BaseObserver {
|
|
|
30
30
|
return { updated: true, persisted_sync_rules, lock: persisted_sync_rules.current_lock ?? undefined };
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Get the sync config used for querying.
|
|
35
|
-
*/
|
|
36
|
-
async getActiveSyncRules(options) {
|
|
37
|
-
const content = await this.getActiveSyncRulesContent();
|
|
38
|
-
return content?.parsed(options) ?? null;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Get the sync config that will be active next once done with initial replicatino.
|
|
42
|
-
*/
|
|
43
|
-
async getNextSyncRules(options) {
|
|
44
|
-
const content = await this.getNextSyncRulesContent();
|
|
45
|
-
return content?.parsed(options) ?? null;
|
|
46
|
-
}
|
|
47
33
|
}
|
|
48
34
|
export function updateSyncRulesFromYaml(content, options) {
|
|
49
35
|
const config = SqlSyncRules.fromYaml(content, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BucketStorageFactory.js","sourceRoot":"","sources":["../../src/storage/BucketStorageFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EACL,qBAAqB,
|
|
1
|
+
{"version":3,"file":"BucketStorageFactory.js","sourceRoot":"","sources":["../../src/storage/BucketStorageFactory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { HydratedSyncConfig, HydrationState, SyncConfigWithErrors } from '@powersync/service-sync-rules';
|
|
2
|
+
/**
|
|
3
|
+
* A parsed sync config set is the identity boundary for parsed sync config state.
|
|
4
|
+
*
|
|
5
|
+
* All values on a single instance - the parsed configs, hydration state and hydrated
|
|
6
|
+
* sync config - are derived from the same parse, and may be associated with each other
|
|
7
|
+
* by object identity. Values from two different instances must never be mixed, even if
|
|
8
|
+
* they were parsed from the same persisted content.
|
|
9
|
+
*/
|
|
10
|
+
export interface ParsedSyncConfigSet {
|
|
11
|
+
readonly replicationStreamId: number;
|
|
12
|
+
readonly replicationStreamName: string;
|
|
13
|
+
readonly syncConfigs: SyncConfigWithErrors[];
|
|
14
|
+
/**
|
|
15
|
+
* For testing only.
|
|
16
|
+
*/
|
|
17
|
+
readonly hydrationState: HydrationState;
|
|
18
|
+
/**
|
|
19
|
+
* The hydrated sync config for this parse. This is a stable property: repeated reads
|
|
20
|
+
* return the same instance.
|
|
21
|
+
*/
|
|
22
|
+
readonly hydratedSyncConfig: HydratedSyncConfig;
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ParsedSyncConfigSet.js","sourceRoot":"","sources":["../../src/storage/ParsedSyncConfigSet.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Logger } from 'winston';
|
|
2
|
+
import { SyncRuleState } from './BucketStorage.js';
|
|
3
|
+
import type { ParsedSyncConfigSet } from './ParsedSyncConfigSet.js';
|
|
4
|
+
import type { ParseSyncConfigOptions, PersistedSyncConfigContent } from './PersistedSyncConfigContent.js';
|
|
5
|
+
import { ReplicationLock } from './ReplicationLock.js';
|
|
6
|
+
import { StorageVersionConfig } from './StorageVersionConfig.js';
|
|
7
|
+
export declare abstract class PersistedReplicationStream implements PersistedReplicationStreamData {
|
|
8
|
+
readonly replicationStreamId: number;
|
|
9
|
+
readonly replicationJobId: string;
|
|
10
|
+
readonly replicationStreamName: string;
|
|
11
|
+
readonly state: SyncRuleState;
|
|
12
|
+
readonly storageVersion: number;
|
|
13
|
+
readonly logger: Logger;
|
|
14
|
+
abstract readonly syncConfigContent: readonly PersistedSyncConfigContent[];
|
|
15
|
+
abstract readonly current_lock: ReplicationLock | null;
|
|
16
|
+
constructor(data: PersistedReplicationStreamData);
|
|
17
|
+
getStorageConfig(): StorageVersionConfig;
|
|
18
|
+
abstract lock(): Promise<ReplicationLock>;
|
|
19
|
+
abstract parsed(options: ParseSyncConfigOptions): ParsedSyncConfigSet;
|
|
20
|
+
}
|
|
21
|
+
export interface PersistedReplicationStreamData {
|
|
22
|
+
readonly replicationStreamId: number;
|
|
23
|
+
readonly replicationStreamName: string;
|
|
24
|
+
readonly state: SyncRuleState;
|
|
25
|
+
readonly storageVersion: number;
|
|
26
|
+
/**
|
|
27
|
+
* Uniquely identifies a job, as a combination of replication stream and processing sync configs.
|
|
28
|
+
*
|
|
29
|
+
* Used in-memory only.
|
|
30
|
+
*/
|
|
31
|
+
readonly replicationJobId?: string;
|
|
32
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { logger as defaultLogger, ErrorCode, ServiceError } from '@powersync/lib-services-framework';
|
|
2
|
+
import { STORAGE_VERSION_CONFIG } from './StorageVersionConfig.js';
|
|
3
|
+
export class PersistedReplicationStream {
|
|
4
|
+
replicationStreamId;
|
|
5
|
+
replicationJobId;
|
|
6
|
+
replicationStreamName;
|
|
7
|
+
state;
|
|
8
|
+
storageVersion;
|
|
9
|
+
logger;
|
|
10
|
+
constructor(data) {
|
|
11
|
+
this.replicationStreamId = data.replicationStreamId;
|
|
12
|
+
this.replicationJobId = data.replicationJobId ?? String(data.replicationStreamId);
|
|
13
|
+
this.replicationStreamName = data.replicationStreamName;
|
|
14
|
+
this.state = data.state;
|
|
15
|
+
this.storageVersion = data.storageVersion;
|
|
16
|
+
this.logger = defaultLogger.child({ prefix: `[${this.replicationStreamName}] ` });
|
|
17
|
+
}
|
|
18
|
+
getStorageConfig() {
|
|
19
|
+
const storageConfig = STORAGE_VERSION_CONFIG[this.storageVersion];
|
|
20
|
+
if (storageConfig == null) {
|
|
21
|
+
throw new ServiceError(ErrorCode.PSYNC_S1005, `Unsupported storage version ${this.storageVersion} for replication stream ${this.replicationStreamId}`);
|
|
22
|
+
}
|
|
23
|
+
return storageConfig;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=PersistedReplicationStream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PersistedReplicationStream.js","sourceRoot":"","sources":["../../src/storage/PersistedReplicationStream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAMrG,OAAO,EAAE,sBAAsB,EAAwB,MAAM,2BAA2B,CAAC;AAEzF,MAAM,OAAgB,0BAA0B;IACrC,mBAAmB,CAAS;IAC5B,gBAAgB,CAAS;IACzB,qBAAqB,CAAS;IAC9B,KAAK,CAAgB;IACrB,cAAc,CAAS;IACvB,MAAM,CAAS;IAKxB,YAAY,IAAoC;QAC9C,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC;QACpD,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,IAAI,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAClF,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,qBAAqB,CAAC;QACxD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,IAAI,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,gBAAgB;QACd,MAAM,aAAa,GAAG,sBAAsB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAClE,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;YAC1B,MAAM,IAAI,YAAY,CACpB,SAAS,CAAC,WAAW,EACrB,+BAA+B,IAAI,CAAC,cAAc,2BAA2B,IAAI,CAAC,mBAAmB,EAAE,CACxG,CAAC;QACJ,CAAC;QACD,OAAO,aAAa,CAAC;IACvB,CAAC;CAKF"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { SyncConfigWithErrors } from '@powersync/service-sync-rules';
|
|
2
|
+
import { Logger } from 'winston';
|
|
3
|
+
import { SerializedSyncPlan, UpdateSyncRulesOptions } from './BucketStorageFactory.js';
|
|
4
|
+
import { ParsedSyncConfigSet } from './ParsedSyncConfigSet.js';
|
|
5
|
+
import { PersistedSyncConfigStatus } from './PersistedSyncConfigStatus.js';
|
|
6
|
+
import { StorageVersionConfig } from './StorageVersionConfig.js';
|
|
7
|
+
export interface ParsePersistedSyncConfigContentOptions {
|
|
8
|
+
content: string;
|
|
9
|
+
compiledPlan: SerializedSyncPlan | null;
|
|
10
|
+
storageVersion: number;
|
|
11
|
+
parseOptions: ParseSyncConfigOptions;
|
|
12
|
+
}
|
|
13
|
+
export declare function parsePersistedSyncConfigContent(options: ParsePersistedSyncConfigContentOptions): SyncConfigWithErrors;
|
|
14
|
+
/**
|
|
15
|
+
* Immutable sync config content for one sync config inside a replication stream.
|
|
16
|
+
*
|
|
17
|
+
* This represents the persisted config content. Fetch per-config status with
|
|
18
|
+
* {@link getSyncConfigStatus}. Use {@link PersistedReplicationStream} for stream
|
|
19
|
+
* lifecycle concerns such as locking and termination.
|
|
20
|
+
*/
|
|
21
|
+
export declare abstract class PersistedSyncConfigContent implements PersistedSyncConfigContentData {
|
|
22
|
+
readonly replicationStreamId: number;
|
|
23
|
+
readonly sync_rules_content: string;
|
|
24
|
+
readonly compiled_plan: SerializedSyncPlan | null;
|
|
25
|
+
readonly replicationStreamName: string;
|
|
26
|
+
readonly storageVersion: number;
|
|
27
|
+
readonly logger: Logger;
|
|
28
|
+
readonly syncConfigId: PersistedSyncConfigId | null;
|
|
29
|
+
constructor(data: PersistedSyncConfigContentData);
|
|
30
|
+
/**
|
|
31
|
+
* Load the storage config.
|
|
32
|
+
*
|
|
33
|
+
* This may throw if the persisted storage version is not supported.
|
|
34
|
+
*/
|
|
35
|
+
getStorageConfig(): StorageVersionConfig;
|
|
36
|
+
/**
|
|
37
|
+
* Parse only this config's content into a single {@link SyncConfigWithErrors}.
|
|
38
|
+
*
|
|
39
|
+
* This does not depend on any other configs in the same replication stream.
|
|
40
|
+
*/
|
|
41
|
+
protected parseSingleConfig(options: ParseSyncConfigOptions): SyncConfigWithErrors;
|
|
42
|
+
parsed(options: ParseSyncConfigOptions): ParsedSyncConfigSet;
|
|
43
|
+
asUpdateOptions(options?: Omit<UpdateSyncRulesOptions, 'config'>): UpdateSyncRulesOptions;
|
|
44
|
+
/**
|
|
45
|
+
* Fetch the current persisted state for this exact sync config.
|
|
46
|
+
*/
|
|
47
|
+
abstract getSyncConfigStatus(): Promise<PersistedSyncConfigStatus | null>;
|
|
48
|
+
}
|
|
49
|
+
export interface PersistedSyncConfigContentData {
|
|
50
|
+
readonly replicationStreamId: number;
|
|
51
|
+
readonly sync_rules_content: string;
|
|
52
|
+
readonly compiled_plan: SerializedSyncPlan | null;
|
|
53
|
+
readonly replicationStreamName: string;
|
|
54
|
+
readonly storageVersion: number;
|
|
55
|
+
readonly syncConfigId?: PersistedSyncConfigId | null;
|
|
56
|
+
}
|
|
57
|
+
export type PersistedSyncConfigId = string;
|
|
58
|
+
export interface ParseSyncConfigOptions {
|
|
59
|
+
defaultSchema: string;
|
|
60
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { logger as defaultLogger, ErrorCode, ServiceError } from '@powersync/lib-services-framework';
|
|
2
|
+
import { CompatibilityContext, CompatibilityOption, DEFAULT_HYDRATION_STATE, deserializeSyncPlan, nodeSqlite, PrecompiledSyncConfig, SqlEventDescriptor, SqlSyncRules, versionedHydrationState, YamlError } from '@powersync/service-sync-rules';
|
|
3
|
+
import * as sqlite from 'node:sqlite';
|
|
4
|
+
import { STORAGE_VERSION_CONFIG } from './StorageVersionConfig.js';
|
|
5
|
+
export function parsePersistedSyncConfigContent(options) {
|
|
6
|
+
const { content, compiledPlan, storageVersion, parseOptions } = options;
|
|
7
|
+
if (compiledPlan == null) {
|
|
8
|
+
// Fallback: Only parse from YAML if no compiled plan is available.
|
|
9
|
+
return SqlSyncRules.fromYaml(content, parseOptions);
|
|
10
|
+
}
|
|
11
|
+
const plan = deserializeSyncPlan(compiledPlan.plan);
|
|
12
|
+
const compatibility = CompatibilityContext.deserialize(compiledPlan.compatibility);
|
|
13
|
+
const eventDefinitions = [];
|
|
14
|
+
for (const [name, queries] of Object.entries(compiledPlan.eventDescriptors)) {
|
|
15
|
+
const descriptor = new SqlEventDescriptor(name, compatibility);
|
|
16
|
+
for (const query of queries) {
|
|
17
|
+
descriptor.addSourceQuery(query, parseOptions);
|
|
18
|
+
}
|
|
19
|
+
eventDefinitions.push(descriptor);
|
|
20
|
+
}
|
|
21
|
+
const precompiled = new PrecompiledSyncConfig(plan, compatibility, eventDefinitions, {
|
|
22
|
+
defaultSchema: parseOptions.defaultSchema,
|
|
23
|
+
sourceText: content
|
|
24
|
+
});
|
|
25
|
+
// Note: If the original content did not define a storage version, this will still set the storage version.
|
|
26
|
+
// This means asUpdateOptions will not change the storage version, even if the default changes.
|
|
27
|
+
precompiled.storageVersion = storageVersion;
|
|
28
|
+
const errors = [];
|
|
29
|
+
if (compiledPlan.errors) {
|
|
30
|
+
for (const error of compiledPlan.errors) {
|
|
31
|
+
const location = error.location && {
|
|
32
|
+
start: error.location.start_offset,
|
|
33
|
+
end: error.location.end_offset
|
|
34
|
+
};
|
|
35
|
+
const asYamlError = new YamlError(new Error(error.message), location);
|
|
36
|
+
asYamlError.type = error.level;
|
|
37
|
+
errors.push(asYamlError);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { config: precompiled, errors };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Immutable sync config content for one sync config inside a replication stream.
|
|
44
|
+
*
|
|
45
|
+
* This represents the persisted config content. Fetch per-config status with
|
|
46
|
+
* {@link getSyncConfigStatus}. Use {@link PersistedReplicationStream} for stream
|
|
47
|
+
* lifecycle concerns such as locking and termination.
|
|
48
|
+
*/
|
|
49
|
+
export class PersistedSyncConfigContent {
|
|
50
|
+
replicationStreamId;
|
|
51
|
+
sync_rules_content;
|
|
52
|
+
compiled_plan;
|
|
53
|
+
replicationStreamName;
|
|
54
|
+
storageVersion;
|
|
55
|
+
logger;
|
|
56
|
+
syncConfigId;
|
|
57
|
+
constructor(data) {
|
|
58
|
+
this.replicationStreamId = data.replicationStreamId;
|
|
59
|
+
this.sync_rules_content = data.sync_rules_content;
|
|
60
|
+
this.compiled_plan = data.compiled_plan;
|
|
61
|
+
this.replicationStreamName = data.replicationStreamName;
|
|
62
|
+
this.storageVersion = data.storageVersion;
|
|
63
|
+
this.syncConfigId = data.syncConfigId ?? null;
|
|
64
|
+
this.logger = defaultLogger.child({ prefix: `[${this.replicationStreamName}] ` });
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Load the storage config.
|
|
68
|
+
*
|
|
69
|
+
* This may throw if the persisted storage version is not supported.
|
|
70
|
+
*/
|
|
71
|
+
getStorageConfig() {
|
|
72
|
+
const storageConfig = STORAGE_VERSION_CONFIG[this.storageVersion];
|
|
73
|
+
if (storageConfig == null) {
|
|
74
|
+
throw new ServiceError(ErrorCode.PSYNC_S1005, `Unsupported storage version ${this.storageVersion} for replication stream ${this.replicationStreamId}`);
|
|
75
|
+
}
|
|
76
|
+
return storageConfig;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Parse only this config's content into a single {@link SyncConfigWithErrors}.
|
|
80
|
+
*
|
|
81
|
+
* This does not depend on any other configs in the same replication stream.
|
|
82
|
+
*/
|
|
83
|
+
parseSingleConfig(options) {
|
|
84
|
+
return parsePersistedSyncConfigContent({
|
|
85
|
+
content: this.sync_rules_content,
|
|
86
|
+
compiledPlan: this.compiled_plan,
|
|
87
|
+
storageVersion: this.storageVersion,
|
|
88
|
+
parseOptions: options
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
parsed(options) {
|
|
92
|
+
let hydrationState;
|
|
93
|
+
const config = this.parseSingleConfig(options);
|
|
94
|
+
const storageConfig = this.getStorageConfig();
|
|
95
|
+
if (storageConfig.versionedBuckets ||
|
|
96
|
+
config.config.compatibility.isEnabled(CompatibilityOption.versionedBucketIds)) {
|
|
97
|
+
hydrationState = versionedHydrationState(this.replicationStreamId);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
hydrationState = DEFAULT_HYDRATION_STATE;
|
|
101
|
+
}
|
|
102
|
+
let hydrated;
|
|
103
|
+
return {
|
|
104
|
+
replicationStreamId: this.replicationStreamId,
|
|
105
|
+
replicationStreamName: this.replicationStreamName,
|
|
106
|
+
syncConfigs: [config],
|
|
107
|
+
hydrationState,
|
|
108
|
+
get hydratedSyncConfig() {
|
|
109
|
+
hydrated ??= config.config.hydrate({ hydrationState, sqlite: nodeSqlite(sqlite) });
|
|
110
|
+
return hydrated;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
asUpdateOptions(options) {
|
|
115
|
+
// defaultSchema is not relevant for the parsed version here
|
|
116
|
+
const parsed = this.parseSingleConfig({ defaultSchema: 'not_applicable' });
|
|
117
|
+
return {
|
|
118
|
+
config: { yaml: this.sync_rules_content, plan: this.compiled_plan, parsed },
|
|
119
|
+
...options
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=PersistedSyncConfigContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PersistedSyncConfigContent.js","sourceRoot":"","sources":["../../src/storage/PersistedSyncConfigContent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SyncRuleState } from './BucketStorage.js';
|
|
2
|
+
import { PersistedSyncConfigId } from './PersistedSyncConfigContent.js';
|
|
3
|
+
export interface PersistedSyncConfigStatus {
|
|
4
|
+
readonly id: PersistedSyncConfigId;
|
|
5
|
+
readonly replicationStreamId: number;
|
|
6
|
+
readonly state: SyncRuleState;
|
|
7
|
+
readonly snapshot_done?: boolean;
|
|
8
|
+
readonly last_checkpoint_lsn: string | null;
|
|
9
|
+
readonly last_fatal_error?: string | null;
|
|
10
|
+
readonly last_fatal_error_ts?: Date | null;
|
|
11
|
+
readonly last_keepalive_ts?: Date | null;
|
|
12
|
+
readonly last_checkpoint_ts?: Date | null;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PersistedSyncConfigStatus.js","sourceRoot":"","sources":["../../src/storage/PersistedSyncConfigStatus.ts"],"names":[],"mappings":""}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BucketDataSource, ParameterIndexLookupCreator, SourceTableRef } from '@powersync/service-sync-rules';
|
|
1
|
+
import { BucketDataSource, BucketDefinitionId, ParameterIndexId, ParameterIndexLookupCreator, SourceTableRef } from '@powersync/service-sync-rules';
|
|
2
2
|
import { bson } from '../index.js';
|
|
3
3
|
import { ColumnDescriptor } from './SourceEntity.js';
|
|
4
4
|
/**
|
|
@@ -13,6 +13,8 @@ export interface SourceTableOptions {
|
|
|
13
13
|
snapshotComplete: boolean;
|
|
14
14
|
bucketDataSources: BucketDataSource[];
|
|
15
15
|
parameterLookupSources: ParameterIndexLookupCreator[];
|
|
16
|
+
bucketDataSourceIds?: Set<BucketDefinitionId>;
|
|
17
|
+
parameterLookupSourceIds?: Set<ParameterIndexId>;
|
|
16
18
|
}
|
|
17
19
|
export interface TableSnapshotStatus {
|
|
18
20
|
totalEstimatedCount: number;
|
|
@@ -45,9 +47,11 @@ export declare class SourceTable {
|
|
|
45
47
|
*/
|
|
46
48
|
syncParameters: boolean;
|
|
47
49
|
/**
|
|
48
|
-
* True if
|
|
50
|
+
* True if this table should fire events for row changes.
|
|
49
51
|
*
|
|
50
|
-
* This value is resolved externally, and cached here.
|
|
52
|
+
* This value is resolved externally, and cached here. When multiple SourceTables exist
|
|
53
|
+
* for the same SourceTableRef (v3 storage), resolveTables designates exactly one of them
|
|
54
|
+
* as the event carrier, so that a row change saved once per table fires each event once.
|
|
51
55
|
*
|
|
52
56
|
* Defaults to true for tests.
|
|
53
57
|
*/
|
|
@@ -80,6 +84,8 @@ export declare class SourceTable {
|
|
|
80
84
|
get replicaIdColumns(): ColumnDescriptor[];
|
|
81
85
|
get bucketDataSources(): BucketDataSource[];
|
|
82
86
|
get parameterLookupSources(): ParameterIndexLookupCreator[];
|
|
87
|
+
get bucketDataSourceIds(): Set<string> | undefined;
|
|
88
|
+
get parameterLookupSourceIds(): Set<string> | undefined;
|
|
83
89
|
/**
|
|
84
90
|
* Sanitized name of the entity in the format of "{schema}.{entity name}".
|
|
85
91
|
* Suitable for safe use in Postgres queries.
|
|
@@ -26,9 +26,11 @@ export class SourceTable {
|
|
|
26
26
|
*/
|
|
27
27
|
syncParameters = true;
|
|
28
28
|
/**
|
|
29
|
-
* True if
|
|
29
|
+
* True if this table should fire events for row changes.
|
|
30
30
|
*
|
|
31
|
-
* This value is resolved externally, and cached here.
|
|
31
|
+
* This value is resolved externally, and cached here. When multiple SourceTables exist
|
|
32
|
+
* for the same SourceTableRef (v3 storage), resolveTables designates exactly one of them
|
|
33
|
+
* as the event carrier, so that a row change saved once per table fires each event once.
|
|
32
34
|
*
|
|
33
35
|
* Defaults to true for tests.
|
|
34
36
|
*/
|
|
@@ -80,6 +82,12 @@ export class SourceTable {
|
|
|
80
82
|
get parameterLookupSources() {
|
|
81
83
|
return this.options.parameterLookupSources;
|
|
82
84
|
}
|
|
85
|
+
get bucketDataSourceIds() {
|
|
86
|
+
return this.options.bucketDataSourceIds;
|
|
87
|
+
}
|
|
88
|
+
get parameterLookupSourceIds() {
|
|
89
|
+
return this.options.parameterLookupSourceIds;
|
|
90
|
+
}
|
|
83
91
|
/**
|
|
84
92
|
* Sanitized name of the entity in the format of "{schema}.{entity name}".
|
|
85
93
|
* Suitable for safe use in Postgres queries.
|
|
@@ -101,7 +109,9 @@ export class SourceTable {
|
|
|
101
109
|
replicaIdColumns: this.replicaIdColumns,
|
|
102
110
|
snapshotComplete: this.snapshotComplete,
|
|
103
111
|
bucketDataSources: this.bucketDataSources,
|
|
104
|
-
parameterLookupSources: this.parameterLookupSources
|
|
112
|
+
parameterLookupSources: this.parameterLookupSources,
|
|
113
|
+
bucketDataSourceIds: this.bucketDataSourceIds == null ? undefined : new Set(this.bucketDataSourceIds),
|
|
114
|
+
parameterLookupSourceIds: this.parameterLookupSourceIds == null ? undefined : new Set(this.parameterLookupSourceIds)
|
|
105
115
|
});
|
|
106
116
|
copy.syncData = this.syncData;
|
|
107
117
|
copy.syncParameters = this.syncParameters;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SourceTable.js","sourceRoot":"","sources":["../../src/storage/SourceTable.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"SourceTable.js","sourceRoot":"","sources":["../../src/storage/SourceTable.ts"],"names":[],"mappings":"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"}
|