@powersync/service-module-postgres-storage 0.14.0 → 0.16.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 (83) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/{@types/storage → storage}/PostgresBucketStorageFactory.d.ts +12 -12
  3. package/dist/storage/PostgresBucketStorageFactory.js +57 -52
  4. package/dist/storage/PostgresBucketStorageFactory.js.map +1 -1
  5. package/dist/storage/PostgresReportStorage.js.map +1 -1
  6. package/dist/storage/PostgresStorageProvider.js +1 -1
  7. package/dist/storage/PostgresStorageProvider.js.map +1 -1
  8. package/dist/{@types/storage → storage}/PostgresSyncRulesStorage.d.ts +16 -8
  9. package/dist/storage/PostgresSyncRulesStorage.js +48 -196
  10. package/dist/storage/PostgresSyncRulesStorage.js.map +1 -1
  11. package/dist/{@types/storage → storage}/batch/PostgresBucketBatch.d.ts +13 -5
  12. package/dist/storage/batch/PostgresBucketBatch.js +280 -29
  13. package/dist/storage/batch/PostgresBucketBatch.js.map +1 -1
  14. package/dist/{@types/storage → storage}/storage-index.d.ts +1 -0
  15. package/dist/storage/storage-index.js +1 -0
  16. package/dist/storage/storage-index.js.map +1 -1
  17. package/dist/storage/sync-rules/PostgresPersistedSyncConfigContent.d.ts +17 -0
  18. package/dist/storage/sync-rules/PostgresPersistedSyncConfigContent.js +89 -0
  19. package/dist/storage/sync-rules/PostgresPersistedSyncConfigContent.js.map +1 -0
  20. package/dist/utils/test-utils.js +2 -2
  21. package/dist/utils/test-utils.js.map +1 -1
  22. package/package.json +10 -22
  23. package/src/storage/PostgresBucketStorageFactory.ts +64 -54
  24. package/src/storage/PostgresReportStorage.ts +1 -2
  25. package/src/storage/PostgresStorageProvider.ts +1 -1
  26. package/src/storage/PostgresSyncRulesStorage.ts +51 -211
  27. package/src/storage/batch/PostgresBucketBatch.ts +325 -45
  28. package/src/storage/storage-index.ts +1 -0
  29. package/src/storage/sync-rules/PostgresPersistedSyncConfigContent.ts +97 -0
  30. package/src/utils/test-utils.ts +2 -2
  31. package/test/src/migrations.test.ts +1 -1
  32. package/test/src/storage.test.ts +7 -2
  33. package/test/src/storage_compacting.test.ts +6 -4
  34. package/test/src/storage_sync.test.ts +2 -1
  35. package/test/tsconfig.json +0 -2
  36. package/tsconfig.json +1 -4
  37. package/tsconfig.tsbuildinfo +1 -0
  38. package/dist/.tsbuildinfo +0 -1
  39. package/dist/@types/storage/sync-rules/PostgresPersistedSyncRulesContent.d.ts +0 -9
  40. package/dist/storage/sync-rules/PostgresPersistedSyncRulesContent.js +0 -49
  41. package/dist/storage/sync-rules/PostgresPersistedSyncRulesContent.js.map +0 -1
  42. package/src/storage/sync-rules/PostgresPersistedSyncRulesContent.ts +0 -54
  43. /package/dist/{@types/index.d.ts → index.d.ts} +0 -0
  44. /package/dist/{@types/migrations → migrations}/PostgresMigrationAgent.d.ts +0 -0
  45. /package/dist/{@types/migrations → migrations}/PostgresMigrationStore.d.ts +0 -0
  46. /package/dist/{@types/migrations → migrations}/migration-utils.d.ts +0 -0
  47. /package/dist/{@types/migrations → migrations}/scripts/1684951997326-init.d.ts +0 -0
  48. /package/dist/{@types/migrations → migrations}/scripts/1749024804042-snapshot-progress.d.ts +0 -0
  49. /package/dist/{@types/migrations → migrations}/scripts/1756282360128-connection-reporting.d.ts +0 -0
  50. /package/dist/{@types/migrations → migrations}/scripts/1771232439485-storage-version.d.ts +0 -0
  51. /package/dist/{@types/migrations → migrations}/scripts/1771424826685-current-data-pending-deletes.d.ts +0 -0
  52. /package/dist/{@types/migrations → migrations}/scripts/1771491856000-sync-plan.d.ts +0 -0
  53. /package/dist/{@types/module → module}/PostgresStorageModule.d.ts +0 -0
  54. /package/dist/{@types/storage → storage}/PostgresCompactor.d.ts +0 -0
  55. /package/dist/{@types/storage → storage}/PostgresReportStorage.d.ts +0 -0
  56. /package/dist/{@types/storage → storage}/PostgresStorageProvider.d.ts +0 -0
  57. /package/dist/{@types/storage → storage}/batch/OperationBatch.d.ts +0 -0
  58. /package/dist/{@types/storage → storage}/batch/PostgresPersistedBatch.d.ts +0 -0
  59. /package/dist/{@types/storage → storage}/checkpoints/PostgresWriteCheckpointAPI.d.ts +0 -0
  60. /package/dist/{@types/storage → storage}/current-data-store.d.ts +0 -0
  61. /package/dist/{@types/storage → storage}/table-id.d.ts +0 -0
  62. /package/dist/{@types/types → types}/codecs.d.ts +0 -0
  63. /package/dist/{@types/types → types}/models/ActiveCheckpoint.d.ts +0 -0
  64. /package/dist/{@types/types → types}/models/ActiveCheckpointNotification.d.ts +0 -0
  65. /package/dist/{@types/types → types}/models/BucketData.d.ts +0 -0
  66. /package/dist/{@types/types → types}/models/BucketParameters.d.ts +0 -0
  67. /package/dist/{@types/types → types}/models/CurrentData.d.ts +0 -0
  68. /package/dist/{@types/types → types}/models/Instance.d.ts +0 -0
  69. /package/dist/{@types/types → types}/models/Migration.d.ts +0 -0
  70. /package/dist/{@types/types → types}/models/SdkReporting.d.ts +0 -0
  71. /package/dist/{@types/types → types}/models/SourceTable.d.ts +0 -0
  72. /package/dist/{@types/types → types}/models/SyncRules.d.ts +0 -0
  73. /package/dist/{@types/types → types}/models/WriteCheckpoint.d.ts +0 -0
  74. /package/dist/{@types/types → types}/models/json.d.ts +0 -0
  75. /package/dist/{@types/types → types}/models/models-index.d.ts +0 -0
  76. /package/dist/{@types/types → types}/types.d.ts +0 -0
  77. /package/dist/{@types/utils → utils}/application-name.d.ts +0 -0
  78. /package/dist/{@types/utils → utils}/bson.d.ts +0 -0
  79. /package/dist/{@types/utils → utils}/bucket-data.d.ts +0 -0
  80. /package/dist/{@types/utils → utils}/db.d.ts +0 -0
  81. /package/dist/{@types/utils → utils}/test-utils.d.ts +0 -0
  82. /package/dist/{@types/utils → utils}/ts-codec.d.ts +0 -0
  83. /package/dist/{@types/utils → utils}/utils-index.d.ts +0 -0
@@ -22,7 +22,6 @@ import {
22
22
  import { JSONBig } from '@powersync/service-jsonbig';
23
23
  import * as sync_rules from '@powersync/service-sync-rules';
24
24
  import * as timers from 'timers/promises';
25
- import * as uuid from 'uuid';
26
25
  import { bigint, BIGINT_MAX } from '../types/codecs.js';
27
26
  import { models, RequiredOperationBatchLimits } from '../types/types.js';
28
27
  import { replicaIdToSubkey } from '../utils/bson.js';
@@ -32,7 +31,6 @@ import * as framework from '@powersync/lib-services-framework';
32
31
  import { StatementParam } from '@powersync/service-jpgwire';
33
32
  import { wrapWithAbort } from 'ix/asynciterable/operators/withabort.js';
34
33
  import * as t from 'ts-codec';
35
- import { SourceTableDecoded, StoredRelationId } from '../types/models/SourceTable.js';
36
34
  import { pick } from '../utils/ts-codec.js';
37
35
  import { PostgresBucketBatch } from './batch/PostgresBucketBatch.js';
38
36
  import { PostgresWriteCheckpointAPI } from './checkpoints/PostgresWriteCheckpointAPI.js';
@@ -43,7 +41,7 @@ import { PostgresCompactor } from './PostgresCompactor.js';
43
41
  export type PostgresSyncRulesStorageOptions = {
44
42
  factory: PostgresBucketStorageFactory;
45
43
  db: lib_postgres.DatabaseClient;
46
- sync_rules: storage.PersistedSyncRulesContent;
44
+ replicationStream: storage.PersistedReplicationStream;
47
45
  write_checkpoint_mode?: storage.WriteCheckpointMode;
48
46
  batchLimits: RequiredOperationBatchLimits;
49
47
  };
@@ -54,9 +52,10 @@ export class PostgresSyncRulesStorage
54
52
  {
55
53
  [framework.DO_NOT_LOG] = true;
56
54
 
57
- public readonly group_id: number;
58
- public readonly sync_rules: storage.PersistedSyncRulesContent;
59
- public readonly slot_name: string;
55
+ public readonly replicationStreamId: number;
56
+ public readonly replicationStream: storage.PersistedReplicationStream;
57
+ public readonly sync_rules: storage.PersistedSyncConfigContent;
58
+ public readonly replicationStreamName: string;
60
59
  public readonly factory: PostgresBucketStorageFactory;
61
60
  public readonly storageConfig: StorageVersionConfig;
62
61
  public readonly logger: framework.Logger;
@@ -67,22 +66,27 @@ export class PostgresSyncRulesStorage
67
66
  protected writeCheckpointAPI: PostgresWriteCheckpointAPI;
68
67
  private readonly currentDataStore: PostgresCurrentDataStore;
69
68
 
70
- // TODO we might be able to share this in an abstract class
71
- private parsedSyncRulesCache:
72
- | { parsed: sync_rules.HydratedSyncRules; options: storage.ParseSyncRulesOptions }
73
- | undefined;
69
+ /**
70
+ * Canonical parsed sync config sets, keyed by defaultSchema. Entries are never evicted,
71
+ * so each parse options value maps to exactly one parsed set for the lifetime of this
72
+ * storage instance.
73
+ *
74
+ * TODO we might be able to share this in an abstract class
75
+ */
76
+ private readonly parsedSyncConfigSets = new Map<string, storage.ParsedSyncConfigSet>();
74
77
  private _checksumCache: storage.ChecksumCache | undefined;
75
78
 
76
79
  constructor(protected options: PostgresSyncRulesStorageOptions) {
77
80
  super();
78
- this.group_id = options.sync_rules.id;
81
+ this.replicationStream = options.replicationStream;
82
+ this.replicationStreamId = options.replicationStream.replicationStreamId;
79
83
  this.db = options.db;
80
- this.sync_rules = options.sync_rules;
81
- this.slot_name = options.sync_rules.slot_name;
84
+ this.sync_rules = options.replicationStream.syncConfigContent[0];
85
+ this.replicationStreamName = options.replicationStream.replicationStreamName;
82
86
  this.factory = options.factory;
83
- this.storageConfig = options.sync_rules.getStorageConfig();
87
+ this.storageConfig = options.replicationStream.getStorageConfig();
84
88
  this.currentDataStore = new PostgresCurrentDataStore(this.storageConfig);
85
- this.logger = options.sync_rules.logger;
89
+ this.logger = options.replicationStream.logger;
86
90
 
87
91
  this.writeCheckpointAPI = new PostgresWriteCheckpointAPI({
88
92
  db: this.db,
@@ -108,18 +112,17 @@ export class PostgresSyncRulesStorage
108
112
  return this.writeCheckpointAPI.writeCheckpointMode;
109
113
  }
110
114
 
111
- // TODO we might be able to share this in an abstract class
112
- getParsedSyncRules(options: storage.ParseSyncRulesOptions): sync_rules.HydratedSyncRules {
113
- const { parsed, options: cachedOptions } = this.parsedSyncRulesCache ?? {};
114
- /**
115
- * Check if the cached sync config, if present, had the same options.
116
- * Parse sync config if the options are different or if there is no cached value.
117
- */
118
- if (!parsed || options.defaultSchema != cachedOptions?.defaultSchema) {
119
- this.parsedSyncRulesCache = { parsed: this.sync_rules.parsed(options).hydratedSyncRules(), options };
115
+ getParsedSyncConfigSet(options: storage.ParseSyncConfigOptions): storage.ParsedSyncConfigSet {
116
+ let parsed = this.parsedSyncConfigSets.get(options.defaultSchema);
117
+ if (parsed == null) {
118
+ parsed = this.replicationStream.parsed(options);
119
+ this.parsedSyncConfigSets.set(options.defaultSchema, parsed);
120
120
  }
121
+ return parsed;
122
+ }
121
123
 
122
- return this.parsedSyncRulesCache!.parsed;
124
+ getParsedSyncRules(options: storage.ParseSyncConfigOptions): sync_rules.HydratedSyncConfig {
125
+ return this.getParsedSyncConfigSet(options).hydratedSyncConfig;
123
126
  }
124
127
 
125
128
  async reportError(e: any): Promise<void> {
@@ -129,7 +132,7 @@ export class PostgresSyncRulesStorage
129
132
  SET
130
133
  last_fatal_error = ${{ type: 'varchar', value: message }}
131
134
  WHERE
132
- id = ${{ type: 'int4', value: this.group_id }};
135
+ id = ${{ type: 'int4', value: this.replicationStreamId }};
133
136
  `.execute();
134
137
  }
135
138
 
@@ -141,7 +144,7 @@ export class PostgresSyncRulesStorage
141
144
  maxOpId = checkpoint.checkpoint;
142
145
  }
143
146
 
144
- return new PostgresCompactor(this.db, this.group_id, {
147
+ return new PostgresCompactor(this.db, this.replicationStreamId, {
145
148
  ...options,
146
149
  maxOpId,
147
150
  logger: this.logger
@@ -156,7 +159,7 @@ export class PostgresSyncRulesStorage
156
159
  lastWriteCheckpoint(filters: storage.SyncStorageLastWriteCheckpointFilters): Promise<bigint | null> {
157
160
  return this.writeCheckpointAPI.lastWriteCheckpoint({
158
161
  ...filters,
159
- sync_rules_id: this.group_id
162
+ sync_rules_id: this.replicationStreamId
160
163
  });
161
164
  }
162
165
 
@@ -176,7 +179,7 @@ export class PostgresSyncRulesStorage
176
179
  FROM
177
180
  sync_rules
178
181
  WHERE
179
- id = ${{ type: 'int4', value: this.group_id }}
182
+ id = ${{ type: 'int4', value: this.replicationStreamId }}
180
183
  `
181
184
  .decoded(pick(models.SyncRules, ['last_checkpoint', 'last_checkpoint_lsn']))
182
185
  .first();
@@ -188,168 +191,6 @@ export class PostgresSyncRulesStorage
188
191
  );
189
192
  }
190
193
 
191
- async resolveTable(options: storage.ResolveTableOptions): Promise<storage.ResolveTableResult> {
192
- const { group_id, connection_id, connection_tag, entity_descriptor } = options;
193
-
194
- const { schema, name: table, objectId, replicaIdColumns } = entity_descriptor;
195
-
196
- const normalizedReplicaIdColumns = replicaIdColumns.map((column) => ({
197
- name: column.name,
198
- type: column.type,
199
- // The PGWire returns this as a BigInt. We want to store this as JSONB
200
- type_oid: typeof column.typeId !== 'undefined' ? Number(column.typeId) : column.typeId
201
- }));
202
- return this.db.transaction(async (db) => {
203
- let sourceTableRow: SourceTableDecoded | null;
204
- if (objectId != null) {
205
- sourceTableRow = await db.sql`
206
- SELECT
207
- *
208
- FROM
209
- source_tables
210
- WHERE
211
- group_id = ${{ type: 'int4', value: group_id }}
212
- AND connection_id = ${{ type: 'int4', value: connection_id }}
213
- AND relation_id = ${{ type: 'jsonb', value: { object_id: objectId } satisfies StoredRelationId }}
214
- AND schema_name = ${{ type: 'varchar', value: schema }}
215
- AND table_name = ${{ type: 'varchar', value: table }}
216
- AND replica_id_columns = ${{ type: 'jsonb', value: normalizedReplicaIdColumns }}
217
- `
218
- .decoded(models.SourceTable)
219
- .first();
220
- } else {
221
- sourceTableRow = await db.sql`
222
- SELECT
223
- *
224
- FROM
225
- source_tables
226
- WHERE
227
- group_id = ${{ type: 'int4', value: group_id }}
228
- AND connection_id = ${{ type: 'int4', value: connection_id }}
229
- AND schema_name = ${{ type: 'varchar', value: schema }}
230
- AND table_name = ${{ type: 'varchar', value: table }}
231
- AND replica_id_columns = ${{ type: 'jsonb', value: normalizedReplicaIdColumns }}
232
- `
233
- .decoded(models.SourceTable)
234
- .first();
235
- }
236
-
237
- if (sourceTableRow == null) {
238
- const row = await db.sql`
239
- INSERT INTO
240
- source_tables (
241
- id,
242
- group_id,
243
- connection_id,
244
- relation_id,
245
- schema_name,
246
- table_name,
247
- replica_id_columns
248
- )
249
- VALUES
250
- (
251
- ${{ type: 'varchar', value: uuid.v4() }},
252
- ${{ type: 'int4', value: group_id }},
253
- ${{ type: 'int4', value: connection_id }},
254
- --- The objectId can be string | number | undefined, we store it as jsonb value
255
- ${{ type: 'jsonb', value: { object_id: objectId } satisfies StoredRelationId }},
256
- ${{ type: 'varchar', value: schema }},
257
- ${{ type: 'varchar', value: table }},
258
- ${{ type: 'jsonb', value: normalizedReplicaIdColumns }}
259
- )
260
- RETURNING
261
- *
262
- `
263
- .decoded(models.SourceTable)
264
- .first();
265
- sourceTableRow = row;
266
- }
267
-
268
- const sourceTable = new storage.SourceTable({
269
- id: sourceTableRow!.id,
270
- connectionTag: connection_tag,
271
- objectId: objectId,
272
- schema: schema,
273
- name: table,
274
- replicaIdColumns: replicaIdColumns,
275
- snapshotComplete: sourceTableRow!.snapshot_done ?? true
276
- });
277
- if (!sourceTable.snapshotComplete) {
278
- sourceTable.snapshotStatus = {
279
- totalEstimatedCount: Number(sourceTableRow!.snapshot_total_estimated_count ?? -1n),
280
- replicatedCount: Number(sourceTableRow!.snapshot_replicated_count ?? 0n),
281
- lastKey: sourceTableRow!.snapshot_last_key
282
- };
283
- }
284
- sourceTable.syncEvent = options.sync_rules.tableTriggersEvent(sourceTable);
285
- sourceTable.syncData = options.sync_rules.tableSyncsData(sourceTable);
286
- sourceTable.syncParameters = options.sync_rules.tableSyncsParameters(sourceTable);
287
-
288
- let truncatedTables: SourceTableDecoded[] = [];
289
- if (objectId != null) {
290
- // relation_id present - check for renamed tables
291
- truncatedTables = await db.sql`
292
- SELECT
293
- *
294
- FROM
295
- source_tables
296
- WHERE
297
- group_id = ${{ type: 'int4', value: group_id }}
298
- AND connection_id = ${{ type: 'int4', value: connection_id }}
299
- AND id != ${{ type: 'varchar', value: sourceTableRow!.id }}
300
- AND (
301
- relation_id = ${{ type: 'jsonb', value: { object_id: objectId } satisfies StoredRelationId }}
302
- OR (
303
- schema_name = ${{ type: 'varchar', value: schema }}
304
- AND table_name = ${{ type: 'varchar', value: table }}
305
- )
306
- )
307
- `
308
- .decoded(models.SourceTable)
309
- .rows();
310
- } else {
311
- // relation_id not present - only check for changed replica_id_columns
312
- truncatedTables = await db.sql`
313
- SELECT
314
- *
315
- FROM
316
- source_tables
317
- WHERE
318
- group_id = ${{ type: 'int4', value: group_id }}
319
- AND connection_id = ${{ type: 'int4', value: connection_id }}
320
- AND id != ${{ type: 'varchar', value: sourceTableRow!.id }}
321
- AND (
322
- schema_name = ${{ type: 'varchar', value: schema }}
323
- AND table_name = ${{ type: 'varchar', value: table }}
324
- )
325
- `
326
- .decoded(models.SourceTable)
327
- .rows();
328
- }
329
-
330
- return {
331
- table: sourceTable,
332
- dropTables: truncatedTables.map(
333
- (doc) =>
334
- new storage.SourceTable({
335
- id: doc.id,
336
- connectionTag: connection_tag,
337
- objectId: doc.relation_id?.object_id ?? 0,
338
- schema: doc.schema_name,
339
- name: doc.table_name,
340
- replicaIdColumns:
341
- doc.replica_id_columns?.map((c) => ({
342
- name: c.name,
343
- typeOid: c.typeId,
344
- type: c.type
345
- })) ?? [],
346
- snapshotComplete: doc.snapshot_done ?? true
347
- })
348
- )
349
- };
350
- });
351
- }
352
-
353
194
  async createWriter(options: storage.CreateWriterOptions): Promise<storage.BucketStorageBatch> {
354
195
  const syncRules = await this.db.sql`
355
196
  SELECT
@@ -360,7 +201,7 @@ export class PostgresSyncRulesStorage
360
201
  FROM
361
202
  sync_rules
362
203
  WHERE
363
- id = ${{ type: 'int4', value: this.group_id }}
204
+ id = ${{ type: 'int4', value: this.replicationStreamId }}
364
205
  `
365
206
  .decoded(pick(models.SyncRules, ['last_checkpoint_lsn', 'no_checkpoint_before', 'keepalive_op', 'snapshot_lsn']))
366
207
  .first();
@@ -370,9 +211,9 @@ export class PostgresSyncRulesStorage
370
211
  const writer = new PostgresBucketBatch({
371
212
  logger: options.logger ?? this.logger,
372
213
  db: this.db,
373
- sync_rules: this.sync_rules.parsed(options).hydratedSyncRules(),
374
- group_id: this.group_id,
375
- slot_name: this.slot_name,
214
+ sync_rules: this.getParsedSyncRules(options),
215
+ replicationStreamId: this.replicationStreamId,
216
+ replicationStreamName: this.replicationStreamName,
376
217
  last_checkpoint_lsn: checkpoint_lsn,
377
218
  keep_alive_op: syncRules?.keepalive_op,
378
219
  resumeFromLsn: maxLsn(syncRules?.snapshot_lsn, checkpoint_lsn),
@@ -380,6 +221,7 @@ export class PostgresSyncRulesStorage
380
221
  skip_existing_rows: options.skipExistingRows ?? false,
381
222
  batch_limits: this.options.batchLimits,
382
223
  markRecordUnavailable: options.markRecordUnavailable,
224
+ hooks: options.hooks,
383
225
  storageConfig: this.storageConfig
384
226
  });
385
227
  this.iterateListeners((cb) => cb.batchStarted?.(writer));
@@ -417,7 +259,7 @@ export class PostgresSyncRulesStorage
417
259
  value: lookups.map((l) => storage.serializeLookupBuffer(l).toString('hex'))
418
260
  }}) WITH ORDINALITY AS requested (value, index)
419
261
  WHERE
420
- group_id = ${{ type: 'int4', value: this.group_id }}
262
+ group_id = ${{ type: 'int4', value: this.replicationStreamId }}
421
263
  AND lookup = decode((requested.value ->> 0)::text, 'hex') -- Decode the hex string to bytea
422
264
  AND id <= ${{ type: 'int8', value: checkpoint.checkpoint }}
423
265
  ORDER BY
@@ -544,7 +386,7 @@ export class PostgresSyncRulesStorage
544
386
  LIMIT
545
387
  $3;`,
546
388
  params: [
547
- { type: 'int4', value: this.group_id },
389
+ { type: 'int4', value: this.replicationStreamId },
548
390
  { type: 'int8', value: end },
549
391
  { type: 'int4', value: batchRowLimit },
550
392
  ...filters.flatMap((f) => [
@@ -660,11 +502,11 @@ export class PostgresSyncRulesStorage
660
502
  state = ${{ type: 'varchar', value: storage.SyncRuleState.TERMINATED }},
661
503
  snapshot_done = ${{ type: 'bool', value: false }}
662
504
  WHERE
663
- id = ${{ type: 'int4', value: this.group_id }}
505
+ id = ${{ type: 'int4', value: this.replicationStreamId }}
664
506
  `.execute();
665
507
  }
666
508
 
667
- async getStatus(): Promise<storage.SyncRuleStatus> {
509
+ async getStatus(): Promise<storage.ReplicationStreamStatus> {
668
510
  const syncRulesRow = await this.db.sql`
669
511
  SELECT
670
512
  snapshot_done,
@@ -674,9 +516,9 @@ export class PostgresSyncRulesStorage
674
516
  FROM
675
517
  sync_rules
676
518
  WHERE
677
- id = ${{ type: 'int4', value: this.group_id }}
519
+ id = ${{ type: 'int4', value: this.replicationStreamId }}
678
520
  `
679
- .decoded(pick(models.SyncRules, ['snapshot_done', 'last_checkpoint_lsn', 'state', 'snapshot_lsn']))
521
+ .decoded(pick(models.SyncRules, ['snapshot_done', 'last_checkpoint_lsn', 'snapshot_lsn']))
680
522
  .first();
681
523
 
682
524
  if (syncRulesRow == null) {
@@ -684,10 +526,8 @@ export class PostgresSyncRulesStorage
684
526
  }
685
527
 
686
528
  return {
687
- snapshot_done: syncRulesRow.snapshot_done,
688
- active: syncRulesRow.state == storage.SyncRuleState.ACTIVE,
689
- checkpoint_lsn: syncRulesRow.last_checkpoint_lsn ?? null,
690
- snapshot_lsn: syncRulesRow.snapshot_lsn ?? null
529
+ snapshotDone: syncRulesRow.snapshot_done && syncRulesRow.last_checkpoint_lsn != null,
530
+ resumeLsn: maxLsn(syncRulesRow.snapshot_lsn, syncRulesRow.last_checkpoint_lsn)
691
531
  };
692
532
  }
693
533
 
@@ -701,27 +541,27 @@ export class PostgresSyncRulesStorage
701
541
  last_checkpoint = NULL,
702
542
  no_checkpoint_before = NULL
703
543
  WHERE
704
- id = ${{ type: 'int4', value: this.group_id }}
544
+ id = ${{ type: 'int4', value: this.replicationStreamId }}
705
545
  `.execute();
706
546
 
707
547
  await this.db.sql`
708
548
  DELETE FROM bucket_data
709
549
  WHERE
710
- group_id = ${{ type: 'int4', value: this.group_id }}
550
+ group_id = ${{ type: 'int4', value: this.replicationStreamId }}
711
551
  `.execute();
712
552
 
713
553
  await this.db.sql`
714
554
  DELETE FROM bucket_parameters
715
555
  WHERE
716
- group_id = ${{ type: 'int4', value: this.group_id }}
556
+ group_id = ${{ type: 'int4', value: this.replicationStreamId }}
717
557
  `.execute();
718
558
 
719
- await this.currentDataStore.deleteGroupRows(this.db, { groupId: this.group_id });
559
+ await this.currentDataStore.deleteGroupRows(this.db, { groupId: this.replicationStreamId });
720
560
 
721
561
  await this.db.sql`
722
562
  DELETE FROM source_tables
723
563
  WHERE
724
- group_id = ${{ type: 'int4', value: this.group_id }}
564
+ group_id = ${{ type: 'int4', value: this.replicationStreamId }}
725
565
  `.execute();
726
566
  }
727
567
 
@@ -762,7 +602,7 @@ export class PostgresSyncRulesStorage
762
602
  AND b.op_id > f.start_op_id
763
603
  AND b.op_id <= f.end_op_id
764
604
  WHERE
765
- b.group_id = ${{ type: 'int4', value: this.group_id }}
605
+ b.group_id = ${{ type: 'int4', value: this.replicationStreamId }}
766
606
  GROUP BY
767
607
  b.bucket_name;
768
608
  `.rows<{ bucket: string; checksum_total: bigint; total: bigint; has_clear_op: number }>();