@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.
Files changed (113) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/api/RouteAPI.d.ts +2 -2
  3. package/dist/api/diagnostics.d.ts +12 -1
  4. package/dist/api/diagnostics.js +34 -22
  5. package/dist/api/diagnostics.js.map +1 -1
  6. package/dist/entry/commands/compact-action.js +1 -1
  7. package/dist/entry/commands/compact-action.js.map +1 -1
  8. package/dist/modules/AbstractModule.d.ts +6 -2
  9. package/dist/modules/AbstractModule.js.map +1 -1
  10. package/dist/replication/AbstractReplicator.d.ts +2 -2
  11. package/dist/replication/AbstractReplicator.js +24 -23
  12. package/dist/replication/AbstractReplicator.js.map +1 -1
  13. package/dist/replication/ReplicationModule.d.ts +3 -3
  14. package/dist/replication/ReplicationModule.js.map +1 -1
  15. package/dist/routes/configure-fastify.d.ts +12 -12
  16. package/dist/routes/endpoints/admin.d.ts +24 -24
  17. package/dist/routes/endpoints/admin.js +44 -34
  18. package/dist/routes/endpoints/admin.js.map +1 -1
  19. package/dist/routes/endpoints/checkpointing.js +1 -1
  20. package/dist/routes/endpoints/checkpointing.js.map +1 -1
  21. package/dist/routes/endpoints/socket-route.js +1 -1
  22. package/dist/routes/endpoints/socket-route.js.map +1 -1
  23. package/dist/routes/endpoints/sync-rules.js +22 -13
  24. package/dist/routes/endpoints/sync-rules.js.map +1 -1
  25. package/dist/routes/endpoints/sync-stream.js +1 -1
  26. package/dist/routes/endpoints/sync-stream.js.map +1 -1
  27. package/dist/runner/teardown.js +8 -8
  28. package/dist/runner/teardown.js.map +1 -1
  29. package/dist/storage/BucketStorageBatch.d.ts +0 -6
  30. package/dist/storage/BucketStorageBatch.js.map +1 -1
  31. package/dist/storage/BucketStorageFactory.d.ts +22 -27
  32. package/dist/storage/BucketStorageFactory.js +4 -18
  33. package/dist/storage/BucketStorageFactory.js.map +1 -1
  34. package/dist/storage/ParsedSyncConfigSet.d.ts +23 -0
  35. package/dist/storage/ParsedSyncConfigSet.js +2 -0
  36. package/dist/storage/ParsedSyncConfigSet.js.map +1 -0
  37. package/dist/storage/PersistedReplicationStream.d.ts +32 -0
  38. package/dist/storage/PersistedReplicationStream.js +26 -0
  39. package/dist/storage/PersistedReplicationStream.js.map +1 -0
  40. package/dist/storage/PersistedSyncConfigContent.d.ts +60 -0
  41. package/dist/storage/PersistedSyncConfigContent.js +123 -0
  42. package/dist/storage/PersistedSyncConfigContent.js.map +1 -0
  43. package/dist/storage/PersistedSyncConfigStatus.d.ts +13 -0
  44. package/dist/storage/PersistedSyncConfigStatus.js +2 -0
  45. package/dist/storage/PersistedSyncConfigStatus.js.map +1 -0
  46. package/dist/storage/SourceTable.d.ts +9 -3
  47. package/dist/storage/SourceTable.js +13 -3
  48. package/dist/storage/SourceTable.js.map +1 -1
  49. package/dist/storage/SyncRulesBucketStorage.d.ts +59 -16
  50. package/dist/storage/SyncRulesBucketStorage.js.map +1 -1
  51. package/dist/storage/implementation/BucketDefinitionMapping.d.ts +117 -0
  52. package/dist/storage/implementation/BucketDefinitionMapping.js +277 -0
  53. package/dist/storage/implementation/BucketDefinitionMapping.js.map +1 -0
  54. package/dist/storage/implementation/IncrementalReprocessingCompatibility.d.ts +6 -0
  55. package/dist/storage/implementation/IncrementalReprocessingCompatibility.js +31 -0
  56. package/dist/storage/implementation/IncrementalReprocessingCompatibility.js.map +1 -0
  57. package/dist/storage/implementation/IncrementalReprocessingSyncConfigLog.d.ts +17 -0
  58. package/dist/storage/implementation/IncrementalReprocessingSyncConfigLog.js +62 -0
  59. package/dist/storage/implementation/IncrementalReprocessingSyncConfigLog.js.map +1 -0
  60. package/dist/storage/implementation/ReplicationStreamStorageIds.d.ts +15 -0
  61. package/dist/storage/implementation/ReplicationStreamStorageIds.js +20 -0
  62. package/dist/storage/implementation/ReplicationStreamStorageIds.js.map +1 -0
  63. package/dist/storage/storage-index.d.ts +8 -1
  64. package/dist/storage/storage-index.js +8 -1
  65. package/dist/storage/storage-index.js.map +1 -1
  66. package/dist/sync/sync.js +5 -0
  67. package/dist/sync/sync.js.map +1 -1
  68. package/dist/util/checkpointing.js +1 -1
  69. package/dist/util/checkpointing.js.map +1 -1
  70. package/dist/util/config/types.d.ts +1 -1
  71. package/dist/util/lsn.d.ts +4 -0
  72. package/dist/util/lsn.js +10 -0
  73. package/dist/util/lsn.js.map +1 -1
  74. package/package.json +6 -7
  75. package/src/api/RouteAPI.ts +2 -2
  76. package/src/api/diagnostics.ts +43 -26
  77. package/src/entry/commands/compact-action.ts +1 -1
  78. package/src/modules/AbstractModule.ts +6 -2
  79. package/src/replication/AbstractReplicator.ts +27 -26
  80. package/src/replication/ReplicationModule.ts +2 -3
  81. package/src/routes/endpoints/admin.ts +70 -49
  82. package/src/routes/endpoints/checkpointing.ts +1 -1
  83. package/src/routes/endpoints/socket-route.ts +1 -1
  84. package/src/routes/endpoints/sync-rules.ts +23 -13
  85. package/src/routes/endpoints/sync-stream.ts +1 -1
  86. package/src/runner/teardown.ts +8 -8
  87. package/src/storage/BucketStorageBatch.ts +0 -7
  88. package/src/storage/BucketStorageFactory.ts +30 -39
  89. package/src/storage/ParsedSyncConfigSet.ts +25 -0
  90. package/src/storage/PersistedReplicationStream.ts +55 -0
  91. package/src/storage/PersistedSyncConfigContent.ts +188 -0
  92. package/src/storage/PersistedSyncConfigStatus.ts +14 -0
  93. package/src/storage/SourceTable.ts +20 -3
  94. package/src/storage/SyncRulesBucketStorage.ts +64 -16
  95. package/src/storage/implementation/BucketDefinitionMapping.ts +436 -0
  96. package/src/storage/implementation/IncrementalReprocessingCompatibility.ts +41 -0
  97. package/src/storage/implementation/IncrementalReprocessingSyncConfigLog.ts +109 -0
  98. package/src/storage/implementation/ReplicationStreamStorageIds.ts +21 -0
  99. package/src/storage/storage-index.ts +9 -1
  100. package/src/sync/sync.ts +5 -0
  101. package/src/util/checkpointing.ts +1 -1
  102. package/src/util/config/types.ts +1 -1
  103. package/src/util/lsn.ts +9 -0
  104. package/test/src/diagnostics.test.ts +61 -34
  105. package/test/src/module-loader.test.ts +33 -1
  106. package/test/src/routes/admin.test.ts +180 -18
  107. package/test/src/routes/mocks.ts +6 -2
  108. package/tsconfig.json +1 -4
  109. package/tsconfig.tsbuildinfo +1 -1
  110. package/dist/storage/PersistedSyncRulesContent.d.ts +0 -59
  111. package/dist/storage/PersistedSyncRulesContent.js +0 -100
  112. package/dist/storage/PersistedSyncRulesContent.js.map +0 -1
  113. package/src/storage/PersistedSyncRulesContent.ts +0 -174
@@ -5,7 +5,8 @@ import { PerformanceTracer } from '../tracing/PerformanceTracer.js';
5
5
  import * as util from '../util/util-index.js';
6
6
  import { BucketStorageBatch, FlushedResult, SaveUpdate } from './BucketStorageBatch.js';
7
7
  import { BucketStorageFactory } from './BucketStorageFactory.js';
8
- import { ParseSyncRulesOptions } from './PersistedSyncRulesContent.js';
8
+ import { ParsedSyncConfigSet } from './ParsedSyncConfigSet.js';
9
+ import { ParseSyncConfigOptions } from './PersistedSyncConfigContent.js';
9
10
  import { SourceEntityDescriptor } from './SourceEntity.js';
10
11
  import { SourceTable } from './SourceTable.js';
11
12
  import { StorageVersionConfig } from './StorageVersionConfig.js';
@@ -14,8 +15,8 @@ import { SyncStorageWriteCheckpointAPI } from './WriteCheckpointAPI.js';
14
15
  * Storage for a specific replication stream.
15
16
  */
16
17
  export interface SyncRulesBucketStorage extends ObserverClient<SyncRulesBucketStorageListener>, SyncStorageWriteCheckpointAPI {
17
- readonly group_id: number;
18
- readonly slot_name: string;
18
+ readonly replicationStreamId: number;
19
+ readonly replicationStreamName: string;
19
20
  readonly storageConfig: StorageVersionConfig;
20
21
  readonly factory: BucketStorageFactory;
21
22
  readonly logger: Logger;
@@ -29,7 +30,19 @@ export interface SyncRulesBucketStorage extends ObserverClient<SyncRulesBucketSt
29
30
  * @deprecated Use `createWriter()` with `await using` instead.
30
31
  */
31
32
  startBatch(options: CreateWriterOptions, callback: (batch: BucketStorageBatch) => Promise<void>): Promise<FlushedResult | null>;
32
- getParsedSyncRules(options: ParseSyncRulesOptions): HydratedSyncConfig;
33
+ /**
34
+ * Get the canonical parsed sync config set for the given parse options.
35
+ *
36
+ * Repeated calls with the same options return the same instance for the lifetime of
37
+ * this storage instance. This is the identity boundary for parsed sync config state:
38
+ * all operations against this storage instance must use parsed objects from sets
39
+ * returned here, never from an independent parse of the same content.
40
+ */
41
+ getParsedSyncConfigSet(options: ParseSyncConfigOptions): ParsedSyncConfigSet;
42
+ /**
43
+ * Shortcut for `getParsedSyncConfigSet(options).hydratedSyncConfig`.
44
+ */
45
+ getParsedSyncRules(options: ParseSyncConfigOptions): HydratedSyncConfig;
33
46
  /**
34
47
  * Terminate the replication stream.
35
48
  *
@@ -38,7 +51,7 @@ export interface SyncRulesBucketStorage extends ObserverClient<SyncRulesBucketSt
38
51
  * Must only be called on stopped replication streams.
39
52
  */
40
53
  terminate(options?: TerminateOptions): Promise<void>;
41
- getStatus(): Promise<SyncRuleStatus>;
54
+ getStatus(): Promise<ReplicationStreamStatus>;
42
55
  /**
43
56
  * Clear the storage, without changing state.
44
57
  */
@@ -100,6 +113,11 @@ export interface SyncRulesBucketStorage extends ObserverClient<SyncRulesBucketSt
100
113
  * Clear checksum cache. Primarily intended for tests.
101
114
  */
102
115
  clearChecksumCache(): void;
116
+ /**
117
+ * Optional storage-provider cleanup for sync configs that have been stopped
118
+ * inside this replication stream.
119
+ */
120
+ cleanupStoppedSyncConfigs?(options: CleanupStoppedSyncConfigsOptions): Promise<CleanupStoppedSyncConfigsResult>;
103
121
  }
104
122
  export interface SyncRulesBucketStorageListener {
105
123
  batchStarted: (batch: BucketStorageBatch) => void;
@@ -113,15 +131,15 @@ export interface BucketChecksumRequest {
113
131
  bucket: string;
114
132
  source: BucketDataSource;
115
133
  }
116
- export interface SyncRuleStatus {
117
- checkpoint_lsn: string | null;
118
- active: boolean;
119
- snapshot_done: boolean;
120
- snapshot_lsn: string | null;
134
+ export interface ReplicationStreamStatus {
135
+ /**
136
+ * Source position to resume replication from.
137
+ */
138
+ resumeLsn: string | null;
121
139
  /**
122
- * Last persisted operation that must be included in the next checkpoint once checkpointing is unblocked.
140
+ * True if _every_ active/processing sync config has a client-visible checkpoint.
123
141
  */
124
- keepalive_op: util.InternalOpId | null;
142
+ snapshotDone: boolean;
125
143
  }
126
144
  export interface ResolveTablesOptions {
127
145
  connection_id: number;
@@ -131,15 +149,15 @@ export interface ResolveTablesOptions {
131
149
  */
132
150
  idGenerator?: () => string | bson.ObjectId;
133
151
  /**
134
- * For tests only - override the sync rules used.
152
+ * For tests only - override the parsed sync config set used.
135
153
  */
136
- syncRules?: HydratedSyncConfig;
154
+ parsedSyncConfig?: ParsedSyncConfigSet;
137
155
  }
138
156
  export interface ResolveTablesResult {
139
157
  tables: SourceTable[];
140
158
  dropTables: SourceTable[];
141
159
  }
142
- export interface CreateWriterOptions extends ParseSyncRulesOptions {
160
+ export interface CreateWriterOptions extends ParseSyncConfigOptions {
143
161
  zeroLSN: string;
144
162
  /**
145
163
  * Whether or not to store a copy of the current data.
@@ -210,6 +228,8 @@ export interface CompactOptions {
210
228
  moveBatchLimit?: number;
211
229
  /** Minimum of 1 */
212
230
  moveBatchQueryLimit?: number;
231
+ /** Byte cap per read batch for streaming compaction. Default 16MB. */
232
+ moveBatchByteLimit?: number;
213
233
  /**
214
234
  * Minimum number new operations in a bucket to trigger compaction of that bucket.
215
235
  *
@@ -230,7 +250,14 @@ export interface CompactOptions {
230
250
  logger?: Logger;
231
251
  }
232
252
  export interface PopulateChecksumCacheOptions {
233
- maxOpId: util.InternalOpId;
253
+ /**
254
+ * Compute checksums up to this op id.
255
+ *
256
+ * Defaults to the highest persisted op id for the replication stream, which covers
257
+ * the common case of populating the cache right after initial replication, before
258
+ * the first checkpoint exists.
259
+ */
260
+ maxOpId?: util.InternalOpId;
234
261
  minBucketChanges?: number;
235
262
  signal?: AbortSignal;
236
263
  }
@@ -243,6 +270,22 @@ export interface PopulateChecksumCacheResults {
243
270
  export interface ClearStorageOptions {
244
271
  signal?: AbortSignal;
245
272
  }
273
+ export interface CleanupStoppedSyncConfigsOptions {
274
+ signal?: AbortSignal;
275
+ logger?: Logger;
276
+ defaultSchema: string;
277
+ sourceConnectionTag: string;
278
+ }
279
+ export interface CleanupStoppedSyncConfigsResult {
280
+ stoppedSyncConfigsRemoved: number;
281
+ bucketDataCollectionsDropped: number;
282
+ parameterIndexCollectionsDropped: number;
283
+ /** Best-effort number, not accurate if the operation takes longer than the timeout. */
284
+ bucketStateDocumentsDeleted: number;
285
+ sourceRecordCollectionsDropped: number;
286
+ sourceTablesUpdated: number;
287
+ sourceTablesDeleted: number;
288
+ }
246
289
  export interface TerminateOptions extends ClearStorageOptions {
247
290
  /**
248
291
  * If true, also clear the storage before terminating.
@@ -1 +1 @@
1
- {"version":3,"file":"SyncRulesBucketStorage.js","sourceRoot":"","sources":["../../src/storage/SyncRulesBucketStorage.ts"],"names":[],"mappings":"AA4VA;;;;GAIG;AACH,MAAM,OAAO,8BAA+B,SAAQ,KAAK;IAE5C;IACA;IAFX,YACW,KAAa,EACb,SAAyC;QAElD,KAAK,CAAC,yCAAyC,KAAK,GAAG,CAAC,CAAC;QAHhD,UAAK,GAAL,KAAK,CAAQ;QACb,cAAS,GAAT,SAAS,CAAgC;IAGpD,CAAC;CACF;AAqDD,MAAM,CAAC,MAAM,yBAAyB,GAAsB;IAC1D,kBAAkB,EAAE,IAAI,GAAG,EAAU;IACrC,qBAAqB,EAAE,IAAI;IAC3B,uBAAuB,EAAE,IAAI,GAAG,EAAU;IAC1C,0BAA0B,EAAE,IAAI;CACjC,CAAC"}
1
+ {"version":3,"file":"SyncRulesBucketStorage.js","sourceRoot":"","sources":["../../src/storage/SyncRulesBucketStorage.ts"],"names":[],"mappings":"AA4YA;;;;GAIG;AACH,MAAM,OAAO,8BAA+B,SAAQ,KAAK;IAE5C;IACA;IAFX,YACW,KAAa,EACb,SAAyC;QAElD,KAAK,CAAC,yCAAyC,KAAK,GAAG,CAAC,CAAC;QAHhD,UAAK,GAAL,KAAK,CAAQ;QACb,cAAS,GAAT,SAAS,CAAgC;IAGpD,CAAC;CACF;AAqDD,MAAM,CAAC,MAAM,yBAAyB,GAAsB;IAC1D,kBAAkB,EAAE,IAAI,GAAG,EAAU;IACrC,qBAAqB,EAAE,IAAI;IAC3B,uBAAuB,EAAE,IAAI,GAAG,EAAU;IAC1C,0BAA0B,EAAE,IAAI;CACjC,CAAC"}
@@ -0,0 +1,117 @@
1
+ import { BucketDataSource, BucketDefinitionId, ParameterIndexId, ParameterIndexLookupCreator, ParameterLookupDefinitionId, SerializedSyncPlanV1, SourceTableRef, SyncConfigWithErrors } from '@powersync/service-sync-rules';
2
+ export interface SerializedSyncConfigWithMapping {
3
+ plan: SerializedSyncPlanV1;
4
+ mapping: SingleSyncConfigBucketDefinitionMapping;
5
+ }
6
+ export type IncrementalMappingDefinitionType = 'bucket_data' | 'parameter_lookup';
7
+ export interface IncrementalMappingDefinitionChange {
8
+ type: IncrementalMappingDefinitionType;
9
+ name: string;
10
+ id: BucketDefinitionId | ParameterIndexId;
11
+ }
12
+ export interface IncrementalMappingChanges {
13
+ reusedDefinitions: IncrementalMappingDefinitionChange[];
14
+ addedDefinitions: IncrementalMappingDefinitionChange[];
15
+ }
16
+ export interface IncrementalMappingResult {
17
+ mapping: SingleSyncConfigBucketDefinitionMapping;
18
+ changes: IncrementalMappingChanges;
19
+ }
20
+ export interface SyncConfigWithMapping {
21
+ syncConfigId?: string;
22
+ syncConfig: SyncConfigWithErrors;
23
+ mapping: SingleSyncConfigBucketDefinitionMapping | null;
24
+ }
25
+ export interface SyncConfigWithRequiredMapping {
26
+ syncConfigId: string;
27
+ syncConfig: SyncConfigWithErrors;
28
+ mapping: SingleSyncConfigBucketDefinitionMapping;
29
+ }
30
+ export interface PersistedDefinitionMapping {
31
+ /**
32
+ * Map of uniqueName -> id, unique per replication stream.
33
+ */
34
+ definitions: Record<string, string>;
35
+ /**
36
+ * Map of (lookupName, queryId) -> id, unique per replication stream.
37
+ */
38
+ parameter_indexes: Record<string, string>;
39
+ }
40
+ /**
41
+ * Represents a mapping from bucket data sources and parameter lookup sources to stable IDs used for bucket definition and parameter index persistence.
42
+ *
43
+ * Usage is deliberately restricted: writer/batch paths resolve through their own parsed
44
+ * sync config set's mapping, and read paths resolve through the persisted
45
+ * {@link SingleSyncConfigBucketDefinitionMapping} of the single sync config they serve.
46
+ * Do not construct ad-hoc resolution paths from parsed sources.
47
+ */
48
+ export interface BucketDefinitionMapping {
49
+ /**
50
+ * Given a BucketDataSource within the associated SyncConfig(s), return the BucketDefinitionId, or throw if not found.
51
+ */
52
+ bucketSourceId(source: BucketDataSource): BucketDefinitionId;
53
+ parameterLookupId(source: ParameterIndexLookupCreator): ParameterIndexId;
54
+ allBucketDefinitionIds(): BucketDefinitionId[];
55
+ allParameterIndexIds(): ParameterIndexId[];
56
+ syncConfigIdsForSourceTable(selectedSyncConfigIds: string[], table: SourceTableRef, bucketDataSourceIds: BucketDefinitionId[], parameterLookupSourceIds: ParameterIndexId[]): string[];
57
+ snapshotBlockingSourceTablesFilter(syncConfigId: string): Record<string, unknown>;
58
+ }
59
+ /**
60
+ * A BucketDefinitionMapping associated with a single SyncConfig.
61
+ *
62
+ * Within a single SyncConfig, unique names are the persistence key for bucket definitions,
63
+ * so lookups here are name-based by design. MongoHydrationState and
64
+ * MultiSyncConfigBucketDefinitionMapping handle the mapping across multiple SyncConfigs in
65
+ * the same replication stream, where names are not unique.
66
+ */
67
+ export declare class SingleSyncConfigBucketDefinitionMapping implements BucketDefinitionMapping {
68
+ private definitions;
69
+ private parameterLookupMapping;
70
+ static fromPersistedMapping(mapping: PersistedDefinitionMapping): SingleSyncConfigBucketDefinitionMapping;
71
+ static fromParsedSyncConfig(syncConfig: SyncConfigWithErrors): SingleSyncConfigBucketDefinitionMapping;
72
+ /**
73
+ *
74
+ * @param compatibleConfigs SyncConfigs with definitions that may be re-used
75
+ * @param newPlan
76
+ * @param reservedMappings _all_ mappings used currently and historically for the replication stream; used to construct new ids
77
+ * @returns
78
+ */
79
+ static constructIncrementalMappingFromSerializedPlans(compatibleConfigs: SerializedSyncConfigWithMapping[], newPlan: SerializedSyncPlanV1, reservedMappings: SingleSyncConfigBucketDefinitionMapping[]): SingleSyncConfigBucketDefinitionMapping;
80
+ static constructIncrementalMappingWithChanges(compatibleConfigs: SerializedSyncConfigWithMapping[], newPlan: SerializedSyncPlanV1, reservedMappings: SingleSyncConfigBucketDefinitionMapping[]): IncrementalMappingResult;
81
+ constructor(definitions?: Record<string, BucketDefinitionId>, parameterLookupMapping?: Record<string, ParameterIndexId>);
82
+ bucketSourceId(source: BucketDataSource): BucketDefinitionId;
83
+ bucketSourceIdByName(uniqueName: string): BucketDefinitionId;
84
+ allBucketDefinitionIds(): BucketDefinitionId[];
85
+ bucketDefinitionEntries(): IncrementalMappingDefinitionChange[];
86
+ allParameterIndexIds(): ParameterIndexId[];
87
+ parameterIndexEntries(): IncrementalMappingDefinitionChange[];
88
+ allDefinitionEntries(): IncrementalMappingDefinitionChange[];
89
+ parameterLookupId(source: ParameterIndexLookupCreator): ParameterIndexId;
90
+ parameterLookupIdByKey(key: string): ParameterIndexId;
91
+ serialize(): PersistedDefinitionMapping;
92
+ syncConfigIdsForSourceTable(selectedSyncConfigIds: string[], _table: SourceTableRef, bucketDataSourceIds: BucketDefinitionId[], parameterLookupSourceIds: ParameterIndexId[]): string[];
93
+ snapshotBlockingSourceTablesFilter(_syncConfigId: string): Record<string, unknown>;
94
+ }
95
+ /**
96
+ * A BucketDefinitionMapping across all SyncConfigs of one parse of a replication stream.
97
+ *
98
+ * Source lookups are strictly identity-based: a source that did not come from the parse
99
+ * this mapping was constructed with is an error. Unique names are not unique across sync
100
+ * configs in a replication stream, so there is deliberately no name-based fallback.
101
+ */
102
+ export declare class MultiSyncConfigBucketDefinitionMapping implements BucketDefinitionMapping {
103
+ private bucketDataSourceMappings;
104
+ private bucketDataSourceSyncConfigIdsById;
105
+ private parameterLookupMappings;
106
+ private parameterLookupSyncConfigIdsById;
107
+ private syncConfigsById;
108
+ private mappings;
109
+ constructor(syncConfigs: SyncConfigWithRequiredMapping[]);
110
+ bucketSourceId(source: BucketDataSource): BucketDefinitionId;
111
+ allBucketDefinitionIds(): BucketDefinitionId[];
112
+ parameterLookupId(source: ParameterIndexLookupCreator): ParameterIndexId;
113
+ allParameterIndexIds(): ParameterIndexId[];
114
+ syncConfigIdsForSourceTable(_selectedSyncConfigIds: string[], table: SourceTableRef, bucketDataSourceIds: BucketDefinitionId[], parameterLookupSourceIds: ParameterIndexId[]): string[];
115
+ snapshotBlockingSourceTablesFilter(syncConfigId: string): Record<string, unknown>;
116
+ }
117
+ export declare function parameterLookupKey(id: ParameterLookupDefinitionId): string;
@@ -0,0 +1,277 @@
1
+ import { ServiceAssertionError } from '@powersync/lib-services-framework';
2
+ import { HashMap, serializedStreamBucketDataSourceEquality, serializedStreamParameterIndexLookupCreatorEquality } from '@powersync/service-sync-rules';
3
+ /**
4
+ * A BucketDefinitionMapping associated with a single SyncConfig.
5
+ *
6
+ * Within a single SyncConfig, unique names are the persistence key for bucket definitions,
7
+ * so lookups here are name-based by design. MongoHydrationState and
8
+ * MultiSyncConfigBucketDefinitionMapping handle the mapping across multiple SyncConfigs in
9
+ * the same replication stream, where names are not unique.
10
+ */
11
+ export class SingleSyncConfigBucketDefinitionMapping {
12
+ definitions;
13
+ parameterLookupMapping;
14
+ static fromPersistedMapping(mapping) {
15
+ return new SingleSyncConfigBucketDefinitionMapping(mapping.definitions ?? {}, mapping.parameter_indexes ?? {});
16
+ }
17
+ static fromParsedSyncConfig(syncConfig) {
18
+ const definitionNames = syncConfig.config.bucketDataSources.map((source) => source.uniqueName).sort();
19
+ const parameterKeys = syncConfig.config.bucketParameterLookupSources
20
+ .map((source) => `${source.sourceId.lookupName}#${source.sourceId.queryId}`)
21
+ .sort();
22
+ const definitions = {};
23
+ const parameterLookups = {};
24
+ for (const [index, uniqueName] of definitionNames.entries()) {
25
+ definitions[uniqueName] = (index + 1).toString(16);
26
+ }
27
+ for (const [index, key] of parameterKeys.entries()) {
28
+ parameterLookups[key] = (index + 1).toString(16);
29
+ }
30
+ return new SingleSyncConfigBucketDefinitionMapping(definitions, parameterLookups);
31
+ }
32
+ /**
33
+ *
34
+ * @param compatibleConfigs SyncConfigs with definitions that may be re-used
35
+ * @param newPlan
36
+ * @param reservedMappings _all_ mappings used currently and historically for the replication stream; used to construct new ids
37
+ * @returns
38
+ */
39
+ static constructIncrementalMappingFromSerializedPlans(compatibleConfigs, newPlan, reservedMappings) {
40
+ return this.constructIncrementalMappingWithChanges(compatibleConfigs, newPlan, reservedMappings).mapping;
41
+ }
42
+ static constructIncrementalMappingWithChanges(compatibleConfigs, newPlan, reservedMappings) {
43
+ let nextBucketDefinitionId = reservedMappings
44
+ .map((mapping) => mapping.allBucketDefinitionIds())
45
+ .flat()
46
+ .reduce((maxId, id) => Math.max(maxId, parseInt(id, 16)), 0) + 1;
47
+ function generateNewBucketDefinitionId() {
48
+ const id = nextBucketDefinitionId.toString(16);
49
+ nextBucketDefinitionId++;
50
+ return id;
51
+ }
52
+ let nextParameterIndexId = reservedMappings
53
+ .map((mapping) => mapping.allParameterIndexIds())
54
+ .flat()
55
+ .reduce((maxId, id) => Math.max(maxId, parseInt(id, 16)), 0) + 1;
56
+ function generateNewParameterIndexId() {
57
+ const id = nextParameterIndexId.toString(16);
58
+ nextParameterIndexId++;
59
+ return id;
60
+ }
61
+ const definitions = {};
62
+ const parameterLookups = {};
63
+ const changes = {
64
+ reusedDefinitions: [],
65
+ addedDefinitions: []
66
+ };
67
+ const compatibleBuckets = new HashMap(serializedStreamBucketDataSourceEquality);
68
+ const compatibleParameterLookups = new HashMap(serializedStreamParameterIndexLookupCreatorEquality);
69
+ for (const config of compatibleConfigs) {
70
+ for (const bucket of config.plan.buckets) {
71
+ compatibleBuckets.putIfAbsent({ bucket, dataSources: config.plan.dataSources }, () => config.mapping.bucketSourceIdByName(bucket.uniqueName));
72
+ }
73
+ for (const parameterLookup of config.plan.parameterIndexes) {
74
+ compatibleParameterLookups.putIfAbsent(parameterLookup, () => config.mapping.parameterLookupIdByKey(parameterLookupKey(parameterLookup.lookupScope)));
75
+ }
76
+ }
77
+ for (const bucket of newPlan.buckets) {
78
+ const compatibleId = compatibleBuckets.get({ bucket, dataSources: newPlan.dataSources });
79
+ const id = compatibleId ?? generateNewBucketDefinitionId();
80
+ definitions[bucket.uniqueName] = id;
81
+ const change = {
82
+ type: 'bucket_data',
83
+ name: bucket.uniqueName,
84
+ id
85
+ };
86
+ if (compatibleId == null) {
87
+ changes.addedDefinitions.push(change);
88
+ }
89
+ else {
90
+ changes.reusedDefinitions.push(change);
91
+ }
92
+ }
93
+ for (const parameterLookup of newPlan.parameterIndexes) {
94
+ const compatibleId = compatibleParameterLookups.get(parameterLookup);
95
+ const id = compatibleId ?? generateNewParameterIndexId();
96
+ const key = parameterLookupKey(parameterLookup.lookupScope);
97
+ parameterLookups[key] = id;
98
+ const change = {
99
+ type: 'parameter_lookup',
100
+ name: key,
101
+ id
102
+ };
103
+ if (compatibleId == null) {
104
+ changes.addedDefinitions.push(change);
105
+ }
106
+ else {
107
+ changes.reusedDefinitions.push(change);
108
+ }
109
+ }
110
+ return {
111
+ mapping: new SingleSyncConfigBucketDefinitionMapping(definitions, parameterLookups),
112
+ changes
113
+ };
114
+ }
115
+ constructor(definitions = {}, parameterLookupMapping = {}) {
116
+ this.definitions = definitions;
117
+ this.parameterLookupMapping = parameterLookupMapping;
118
+ }
119
+ bucketSourceId(source) {
120
+ return this.bucketSourceIdByName(source.uniqueName);
121
+ }
122
+ bucketSourceIdByName(uniqueName) {
123
+ const defId = this.definitions[uniqueName];
124
+ if (defId == null) {
125
+ throw new ServiceAssertionError(`No mapping found for bucket source ${uniqueName}`);
126
+ }
127
+ return defId;
128
+ }
129
+ allBucketDefinitionIds() {
130
+ return Object.values(this.definitions);
131
+ }
132
+ bucketDefinitionEntries() {
133
+ return Object.entries(this.definitions).map(([name, id]) => ({
134
+ type: 'bucket_data',
135
+ name,
136
+ id
137
+ }));
138
+ }
139
+ allParameterIndexIds() {
140
+ return Object.values(this.parameterLookupMapping);
141
+ }
142
+ parameterIndexEntries() {
143
+ return Object.entries(this.parameterLookupMapping).map(([name, id]) => ({
144
+ type: 'parameter_lookup',
145
+ name,
146
+ id
147
+ }));
148
+ }
149
+ allDefinitionEntries() {
150
+ return [...this.bucketDefinitionEntries(), ...this.parameterIndexEntries()];
151
+ }
152
+ parameterLookupId(source) {
153
+ return this.parameterLookupIdByKey(parameterLookupKey(source.sourceId));
154
+ }
155
+ parameterLookupIdByKey(key) {
156
+ const defId = this.parameterLookupMapping[key];
157
+ if (defId == null) {
158
+ throw new ServiceAssertionError(`No mapping found for parameter lookup source ${key}`);
159
+ }
160
+ return defId;
161
+ }
162
+ serialize() {
163
+ return {
164
+ definitions: { ...this.definitions },
165
+ parameter_indexes: { ...this.parameterLookupMapping }
166
+ };
167
+ }
168
+ syncConfigIdsForSourceTable(selectedSyncConfigIds, _table, bucketDataSourceIds, parameterLookupSourceIds) {
169
+ return bucketDataSourceIds.length > 0 || parameterLookupSourceIds.length > 0 ? selectedSyncConfigIds : [];
170
+ }
171
+ snapshotBlockingSourceTablesFilter(_syncConfigId) {
172
+ const clauses = [];
173
+ const bucketDataSourceIds = this.allBucketDefinitionIds();
174
+ if (bucketDataSourceIds.length > 0) {
175
+ clauses.push({ bucket_data_source_ids: { $in: bucketDataSourceIds } });
176
+ }
177
+ const parameterLookupSourceIds = this.allParameterIndexIds();
178
+ if (parameterLookupSourceIds.length > 0) {
179
+ clauses.push({ parameter_lookup_source_ids: { $in: parameterLookupSourceIds } });
180
+ }
181
+ if (clauses.length == 0) {
182
+ return {
183
+ snapshot_done: false,
184
+ _id: { $exists: false }
185
+ };
186
+ }
187
+ return {
188
+ snapshot_done: false,
189
+ $or: clauses
190
+ };
191
+ }
192
+ }
193
+ /**
194
+ * A BucketDefinitionMapping across all SyncConfigs of one parse of a replication stream.
195
+ *
196
+ * Source lookups are strictly identity-based: a source that did not come from the parse
197
+ * this mapping was constructed with is an error. Unique names are not unique across sync
198
+ * configs in a replication stream, so there is deliberately no name-based fallback.
199
+ */
200
+ export class MultiSyncConfigBucketDefinitionMapping {
201
+ bucketDataSourceMappings = new WeakMap();
202
+ bucketDataSourceSyncConfigIdsById = new Map();
203
+ parameterLookupMappings = new WeakMap();
204
+ parameterLookupSyncConfigIdsById = new Map();
205
+ syncConfigsById = new Map();
206
+ mappings;
207
+ constructor(syncConfigs) {
208
+ this.mappings = syncConfigs.map((config) => config.mapping);
209
+ for (const config of syncConfigs) {
210
+ this.syncConfigsById.set(config.syncConfigId, config);
211
+ for (const source of config.syncConfig.config.bucketDataSources) {
212
+ this.bucketDataSourceMappings.set(source, config.mapping);
213
+ addSetEntry(this.bucketDataSourceSyncConfigIdsById, config.mapping.bucketSourceId(source), config.syncConfigId);
214
+ }
215
+ for (const source of config.syncConfig.config.bucketParameterLookupSources) {
216
+ this.parameterLookupMappings.set(source, config.mapping);
217
+ addSetEntry(this.parameterLookupSyncConfigIdsById, config.mapping.parameterLookupId(source), config.syncConfigId);
218
+ }
219
+ }
220
+ }
221
+ bucketSourceId(source) {
222
+ const mapping = this.bucketDataSourceMappings.get(source);
223
+ if (mapping == null) {
224
+ throw new ServiceAssertionError(`Bucket source ${source.uniqueName} is not associated with this parse of the sync configs`);
225
+ }
226
+ return mapping.bucketSourceId(source);
227
+ }
228
+ allBucketDefinitionIds() {
229
+ return [...new Set(this.mappings.flatMap((mapping) => mapping.allBucketDefinitionIds()))];
230
+ }
231
+ parameterLookupId(source) {
232
+ const mapping = this.parameterLookupMappings.get(source);
233
+ if (mapping == null) {
234
+ throw new ServiceAssertionError(`Parameter lookup source ${source.sourceId.lookupName}#${source.sourceId.queryId} is not associated with this parse of the sync configs`);
235
+ }
236
+ return mapping.parameterLookupId(source);
237
+ }
238
+ allParameterIndexIds() {
239
+ return [...new Set(this.mappings.flatMap((mapping) => mapping.allParameterIndexIds()))];
240
+ }
241
+ syncConfigIdsForSourceTable(_selectedSyncConfigIds, table, bucketDataSourceIds, parameterLookupSourceIds) {
242
+ const ids = new Set();
243
+ for (const sourceId of bucketDataSourceIds) {
244
+ addAll(ids, this.bucketDataSourceSyncConfigIdsById.get(sourceId));
245
+ }
246
+ for (const sourceId of parameterLookupSourceIds) {
247
+ addAll(ids, this.parameterLookupSyncConfigIdsById.get(sourceId));
248
+ }
249
+ for (const [syncConfigId, config] of this.syncConfigsById) {
250
+ if (config.syncConfig.config.tableTriggersEvent(table)) {
251
+ ids.add(syncConfigId);
252
+ }
253
+ }
254
+ return [...ids];
255
+ }
256
+ snapshotBlockingSourceTablesFilter(syncConfigId) {
257
+ const config = this.syncConfigsById.get(syncConfigId);
258
+ if (config == null) {
259
+ throw new ServiceAssertionError(`No mapping found for sync config ${syncConfigId}`);
260
+ }
261
+ return config.mapping.snapshotBlockingSourceTablesFilter(syncConfigId);
262
+ }
263
+ }
264
+ export function parameterLookupKey(id) {
265
+ return `${id.lookupName}#${id.queryId}`;
266
+ }
267
+ function addSetEntry(map, key, value) {
268
+ const existing = map.get(key) ?? new Set();
269
+ existing.add(value);
270
+ map.set(key, existing);
271
+ }
272
+ function addAll(target, values) {
273
+ for (const value of values ?? []) {
274
+ target.add(value);
275
+ }
276
+ }
277
+ //# sourceMappingURL=BucketDefinitionMapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BucketDefinitionMapping.js","sourceRoot":"","sources":["../../../src/storage/implementation/BucketDefinitionMapping.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Logger } from 'winston';
2
+ import { SerializedSyncPlan, UpdateSyncRulesOptions } from '../BucketStorageFactory.js';
3
+ /**
4
+ * Check if a sync config update can use incremental reprocessing.
5
+ */
6
+ export declare function isCompatible(existingPlans: (SerializedSyncPlan | null)[], updateConfig: UpdateSyncRulesOptions['config'], logger: Logger): boolean;
@@ -0,0 +1,31 @@
1
+ import { CompatibilityContext } from '@powersync/service-sync-rules';
2
+ /**
3
+ * Check if a sync config update can use incremental reprocessing.
4
+ */
5
+ export function isCompatible(existingPlans, updateConfig, logger) {
6
+ if (updateConfig.plan == null) {
7
+ // Only support sync streams with serialized plans
8
+ logger.info(`Not using current sync streams - incremental reprocessing not supported`);
9
+ return false;
10
+ }
11
+ // We don't check the storage version here - that is checked upstream.
12
+ if (existingPlans.length == 0) {
13
+ // Could technically be compatible, but there is no reason to re-use this stream.
14
+ return false;
15
+ }
16
+ if (existingPlans.some((plan) => plan == null)) {
17
+ // Only support sync streams with serialized plans
18
+ logger.info(`Existing replication stream not using current sync streams - incremental reprocessing not supported`);
19
+ return false;
20
+ }
21
+ // Technically we can compare the serialized compatibility versions? But this does not add much overhead.
22
+ const first = existingPlans[0];
23
+ const streamCompatibility = CompatibilityContext.deserialize(first.compatibility);
24
+ if (!streamCompatibility.equals(updateConfig.parsed.config.compatibility)) {
25
+ // Compatibility options must match
26
+ logger.info(`Compatibility options changed - incremental reprocessing not supported`);
27
+ return false;
28
+ }
29
+ return true;
30
+ }
31
+ //# sourceMappingURL=IncrementalReprocessingCompatibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IncrementalReprocessingCompatibility.js","sourceRoot":"","sources":["../../../src/storage/implementation/IncrementalReprocessingCompatibility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAIrE;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,aAA4C,EAC5C,YAA8C,EAC9C,MAAc;IAEd,IAAI,YAAY,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;QAC9B,kDAAkD;QAClD,MAAM,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAC;QACvF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,sEAAsE;IACtE,IAAI,aAAa,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC9B,iFAAiF;QACjF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;QAC/C,kDAAkD;QAClD,MAAM,CAAC,IAAI,CAAC,qGAAqG,CAAC,CAAC;QACnH,OAAO,KAAK,CAAC;IACf,CAAC;IAED,yGAAyG;IACzG,MAAM,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,mBAAmB,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAM,CAAC,aAAa,CAAC,CAAC;IACnF,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QAC1E,mCAAmC;QACnC,MAAM,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;QACtF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { SyncConfigWithErrors } from '@powersync/service-sync-rules';
2
+ import { IncrementalMappingChanges, IncrementalMappingDefinitionChange, SingleSyncConfigBucketDefinitionMapping } from './BucketDefinitionMapping.js';
3
+ export interface IncrementalDefinitionLogEntry extends IncrementalMappingDefinitionChange {
4
+ sourceTables?: string[];
5
+ }
6
+ export interface IncrementalSyncConfigUpdateLog {
7
+ reusedDefinitions: IncrementalDefinitionLogEntry[];
8
+ addedDefinitions: IncrementalDefinitionLogEntry[];
9
+ droppedDefinitions: IncrementalDefinitionLogEntry[];
10
+ }
11
+ export declare function formatIncrementalSyncConfigUpdateLog(log: IncrementalSyncConfigUpdateLog): string;
12
+ export declare function describeIncrementalSyncConfigUpdate(options: {
13
+ activeMappings: SingleSyncConfigBucketDefinitionMapping[];
14
+ newMapping: SingleSyncConfigBucketDefinitionMapping;
15
+ newSyncConfig: SyncConfigWithErrors;
16
+ mappingChanges: IncrementalMappingChanges;
17
+ }): IncrementalSyncConfigUpdateLog;