@powersync/service-module-mssql 0.0.0-dev-20251128080741

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 (92) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/LICENSE +67 -0
  3. package/README.md +3 -0
  4. package/ci/init-mssql.sql +50 -0
  5. package/dist/api/MSSQLRouteAPIAdapter.d.ts +21 -0
  6. package/dist/api/MSSQLRouteAPIAdapter.js +248 -0
  7. package/dist/api/MSSQLRouteAPIAdapter.js.map +1 -0
  8. package/dist/common/LSN.d.ts +37 -0
  9. package/dist/common/LSN.js +64 -0
  10. package/dist/common/LSN.js.map +1 -0
  11. package/dist/common/MSSQLSourceTable.d.ts +27 -0
  12. package/dist/common/MSSQLSourceTable.js +35 -0
  13. package/dist/common/MSSQLSourceTable.js.map +1 -0
  14. package/dist/common/MSSQLSourceTableCache.d.ts +14 -0
  15. package/dist/common/MSSQLSourceTableCache.js +28 -0
  16. package/dist/common/MSSQLSourceTableCache.js.map +1 -0
  17. package/dist/common/mssqls-to-sqlite.d.ts +18 -0
  18. package/dist/common/mssqls-to-sqlite.js +143 -0
  19. package/dist/common/mssqls-to-sqlite.js.map +1 -0
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +2 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/module/MSSQLModule.d.ts +15 -0
  24. package/dist/module/MSSQLModule.js +68 -0
  25. package/dist/module/MSSQLModule.js.map +1 -0
  26. package/dist/replication/CDCPoller.d.ts +67 -0
  27. package/dist/replication/CDCPoller.js +188 -0
  28. package/dist/replication/CDCPoller.js.map +1 -0
  29. package/dist/replication/CDCReplicationJob.d.ts +17 -0
  30. package/dist/replication/CDCReplicationJob.js +76 -0
  31. package/dist/replication/CDCReplicationJob.js.map +1 -0
  32. package/dist/replication/CDCReplicator.d.ts +18 -0
  33. package/dist/replication/CDCReplicator.js +55 -0
  34. package/dist/replication/CDCReplicator.js.map +1 -0
  35. package/dist/replication/CDCStream.d.ts +106 -0
  36. package/dist/replication/CDCStream.js +539 -0
  37. package/dist/replication/CDCStream.js.map +1 -0
  38. package/dist/replication/MSSQLConnectionManager.d.ts +23 -0
  39. package/dist/replication/MSSQLConnectionManager.js +97 -0
  40. package/dist/replication/MSSQLConnectionManager.js.map +1 -0
  41. package/dist/replication/MSSQLConnectionManagerFactory.d.ts +10 -0
  42. package/dist/replication/MSSQLConnectionManagerFactory.js +28 -0
  43. package/dist/replication/MSSQLConnectionManagerFactory.js.map +1 -0
  44. package/dist/replication/MSSQLErrorRateLimiter.d.ts +10 -0
  45. package/dist/replication/MSSQLErrorRateLimiter.js +34 -0
  46. package/dist/replication/MSSQLErrorRateLimiter.js.map +1 -0
  47. package/dist/replication/MSSQLSnapshotQuery.d.ts +71 -0
  48. package/dist/replication/MSSQLSnapshotQuery.js +190 -0
  49. package/dist/replication/MSSQLSnapshotQuery.js.map +1 -0
  50. package/dist/types/mssql-data-types.d.ts +66 -0
  51. package/dist/types/mssql-data-types.js +62 -0
  52. package/dist/types/mssql-data-types.js.map +1 -0
  53. package/dist/types/types.d.ts +177 -0
  54. package/dist/types/types.js +141 -0
  55. package/dist/types/types.js.map +1 -0
  56. package/dist/utils/mssql.d.ts +80 -0
  57. package/dist/utils/mssql.js +329 -0
  58. package/dist/utils/mssql.js.map +1 -0
  59. package/dist/utils/schema.d.ts +21 -0
  60. package/dist/utils/schema.js +131 -0
  61. package/dist/utils/schema.js.map +1 -0
  62. package/package.json +51 -0
  63. package/src/api/MSSQLRouteAPIAdapter.ts +283 -0
  64. package/src/common/LSN.ts +77 -0
  65. package/src/common/MSSQLSourceTable.ts +54 -0
  66. package/src/common/MSSQLSourceTableCache.ts +36 -0
  67. package/src/common/mssqls-to-sqlite.ts +151 -0
  68. package/src/index.ts +1 -0
  69. package/src/module/MSSQLModule.ts +82 -0
  70. package/src/replication/CDCPoller.ts +247 -0
  71. package/src/replication/CDCReplicationJob.ts +87 -0
  72. package/src/replication/CDCReplicator.ts +70 -0
  73. package/src/replication/CDCStream.ts +691 -0
  74. package/src/replication/MSSQLConnectionManager.ts +113 -0
  75. package/src/replication/MSSQLConnectionManagerFactory.ts +33 -0
  76. package/src/replication/MSSQLErrorRateLimiter.ts +36 -0
  77. package/src/replication/MSSQLSnapshotQuery.ts +230 -0
  78. package/src/types/mssql-data-types.ts +79 -0
  79. package/src/types/types.ts +224 -0
  80. package/src/utils/mssql.ts +420 -0
  81. package/src/utils/schema.ts +172 -0
  82. package/test/src/CDCStream.test.ts +204 -0
  83. package/test/src/CDCStreamTestContext.ts +212 -0
  84. package/test/src/CDCStream_resumable_snapshot.test.ts +159 -0
  85. package/test/src/env.ts +11 -0
  86. package/test/src/mssql-to-sqlite.test.ts +474 -0
  87. package/test/src/setup.ts +12 -0
  88. package/test/src/util.ts +188 -0
  89. package/test/tsconfig.json +28 -0
  90. package/tsconfig.json +26 -0
  91. package/tsconfig.tsbuildinfo +1 -0
  92. package/vitest.config.ts +15 -0
@@ -0,0 +1,539 @@
1
+ import { container, DatabaseConnectionError, ErrorCode, logger as defaultLogger, ReplicationAbortedError, ReplicationAssertionError, ServiceAssertionError } from '@powersync/lib-services-framework';
2
+ import { getUuidReplicaIdentityBson, storage } from '@powersync/service-core';
3
+ import { ReplicationMetric } from '@powersync/service-types';
4
+ import { BatchedSnapshotQuery, IdSnapshotQuery, SimpleSnapshotQuery } from './MSSQLSnapshotQuery.js';
5
+ import { getReplicationIdentityColumns, getTablesFromPattern } from '../utils/schema.js';
6
+ import { checkSourceConfiguration, createCheckpoint, getCaptureInstance, getLatestLSN, getLatestReplicatedLSN, isIColumnMetadata, isTableEnabledForCDC, isWithinRetentionThreshold, toQualifiedTableName } from '../utils/mssql.js';
7
+ import sql from 'mssql';
8
+ import { CDCToSqliteRow, toSqliteInputRow } from '../common/mssqls-to-sqlite.js';
9
+ import { LSN } from '../common/LSN.js';
10
+ import { MSSQLSourceTable } from '../common/MSSQLSourceTable.js';
11
+ import { MSSQLSourceTableCache } from '../common/MSSQLSourceTableCache.js';
12
+ import { CDCPoller } from './CDCPoller.js';
13
+ export var SnapshotStatus;
14
+ (function (SnapshotStatus) {
15
+ SnapshotStatus["IN_PROGRESS"] = "in-progress";
16
+ SnapshotStatus["DONE"] = "done";
17
+ SnapshotStatus["RESTART_REQUIRED"] = "restart-required";
18
+ })(SnapshotStatus || (SnapshotStatus = {}));
19
+ export class CDCConfigurationError extends Error {
20
+ constructor(message) {
21
+ super(message);
22
+ }
23
+ }
24
+ /**
25
+ * Thrown when required updates in the CDC instance tables are no longer available
26
+ *
27
+ * Possible reasons:
28
+ * * Older data has been cleaned up due to exceeding the retention period.
29
+ * This can happen if PowerSync was stopped for a long period of time.
30
+ */
31
+ export class CDCDataExpiredError extends DatabaseConnectionError {
32
+ constructor(message, cause) {
33
+ super(ErrorCode.PSYNC_S1500, message, cause);
34
+ }
35
+ }
36
+ export class CDCStream {
37
+ options;
38
+ syncRules;
39
+ storage;
40
+ connections;
41
+ abortSignal;
42
+ logger;
43
+ tableCache = new MSSQLSourceTableCache();
44
+ /**
45
+ * Time of the oldest uncommitted change, according to the source db.
46
+ * This is used to determine the replication lag.
47
+ */
48
+ oldestUncommittedChange = null;
49
+ /**
50
+ * Keep track of whether we have done a commit or keepalive yet.
51
+ * We can only compute replication lag if isStartingReplication == false, or oldestUncommittedChange is present.
52
+ */
53
+ isStartingReplication = true;
54
+ constructor(options) {
55
+ this.options = options;
56
+ this.logger = options.logger ?? defaultLogger;
57
+ this.storage = options.storage;
58
+ this.syncRules = options.storage.getParsedSyncRules({ defaultSchema: options.connections.schema });
59
+ this.connections = options.connections;
60
+ this.abortSignal = options.abortSignal;
61
+ }
62
+ get metrics() {
63
+ return this.options.metrics;
64
+ }
65
+ get stopped() {
66
+ return this.abortSignal.aborted;
67
+ }
68
+ get defaultSchema() {
69
+ return this.connections.schema;
70
+ }
71
+ get groupId() {
72
+ return this.options.storage.group_id;
73
+ }
74
+ get connectionId() {
75
+ const { connectionId } = this.connections;
76
+ // Default to 1 if not set
77
+ if (!connectionId) {
78
+ return 1;
79
+ }
80
+ /**
81
+ * This is often `"default"` (string) which will parse to `NaN`
82
+ */
83
+ const parsed = Number.parseInt(connectionId);
84
+ if (isNaN(parsed)) {
85
+ return 1;
86
+ }
87
+ return parsed;
88
+ }
89
+ get connectionTag() {
90
+ return this.connections.connectionTag;
91
+ }
92
+ get snapshotBatchSize() {
93
+ return this.options.snapshotBatchSize ?? 10_000;
94
+ }
95
+ async replicate() {
96
+ try {
97
+ await this.initReplication();
98
+ await this.streamChanges();
99
+ }
100
+ catch (e) {
101
+ await this.storage.reportError(e);
102
+ throw e;
103
+ }
104
+ }
105
+ async populateTableCache() {
106
+ const sourceTables = this.syncRules.getSourceTables();
107
+ await this.storage.startBatch({
108
+ logger: this.logger,
109
+ zeroLSN: LSN.ZERO,
110
+ defaultSchema: this.defaultSchema,
111
+ storeCurrentData: true
112
+ }, async (batch) => {
113
+ for (let tablePattern of sourceTables) {
114
+ const tables = await this.getQualifiedTableNames(batch, tablePattern);
115
+ for (const table of tables) {
116
+ this.tableCache.set(table);
117
+ }
118
+ }
119
+ });
120
+ }
121
+ async getQualifiedTableNames(batch, tablePattern) {
122
+ if (tablePattern.connectionTag != this.connections.connectionTag) {
123
+ return [];
124
+ }
125
+ const matchedTables = await getTablesFromPattern(this.connections, tablePattern);
126
+ const tables = [];
127
+ for (const matchedTable of matchedTables) {
128
+ const isEnabled = await isTableEnabledForCDC({
129
+ connectionManager: this.connections,
130
+ table: matchedTable.name,
131
+ schema: matchedTable.schema
132
+ });
133
+ if (!isEnabled) {
134
+ this.logger.info(`Skipping ${matchedTable.schema}.${matchedTable.name} - table is not enabled for CDC.`);
135
+ continue;
136
+ }
137
+ // TODO: Check RLS settings for table
138
+ const replicaIdColumns = await getReplicationIdentityColumns({
139
+ connectionManager: this.connections,
140
+ tableName: matchedTable.name,
141
+ schema: matchedTable.schema
142
+ });
143
+ const table = await this.processTable(batch, {
144
+ name: matchedTable.name,
145
+ schema: matchedTable.schema,
146
+ objectId: matchedTable.objectId,
147
+ replicaIdColumns: replicaIdColumns.columns
148
+ }, false);
149
+ tables.push(table);
150
+ }
151
+ return tables;
152
+ }
153
+ async processTable(batch, table, snapshot) {
154
+ if (!table.objectId && typeof table.objectId != 'number') {
155
+ throw new ReplicationAssertionError(`objectId expected, got ${typeof table.objectId}`);
156
+ }
157
+ const resolved = await this.storage.resolveTable({
158
+ group_id: this.groupId,
159
+ connection_id: this.connectionId,
160
+ connection_tag: this.connectionTag,
161
+ entity_descriptor: table,
162
+ sync_rules: this.syncRules
163
+ });
164
+ const captureInstance = await getCaptureInstance({
165
+ connectionManager: this.connections,
166
+ tableName: resolved.table.name,
167
+ schema: resolved.table.schema
168
+ });
169
+ if (!captureInstance) {
170
+ throw new ServiceAssertionError(`Missing capture instance for table ${toQualifiedTableName(resolved.table.schema, resolved.table.name)}`);
171
+ }
172
+ const resolvedTable = new MSSQLSourceTable({
173
+ sourceTable: resolved.table,
174
+ captureInstance: captureInstance
175
+ });
176
+ // Drop conflicting tables. This includes for example renamed tables.
177
+ await batch.drop(resolved.dropTables);
178
+ // Snapshot if:
179
+ // 1. Snapshot is requested (false for initial snapshot, since that process handles it elsewhere)
180
+ // 2. Snapshot is not already done, AND:
181
+ // 3. The table is used in sync rules.
182
+ const shouldSnapshot = snapshot && !resolved.table.snapshotComplete && resolved.table.syncAny;
183
+ if (shouldSnapshot) {
184
+ // Truncate this table in case a previous snapshot was interrupted.
185
+ await batch.truncate([resolved.table]);
186
+ // Start the snapshot inside a transaction.
187
+ try {
188
+ await this.snapshotTableInTx(batch, resolvedTable);
189
+ }
190
+ finally {
191
+ // TODO Cleanup?
192
+ }
193
+ }
194
+ return resolvedTable;
195
+ }
196
+ async snapshotTableInTx(batch, table, limited) {
197
+ // Note: We use the "Read Committed" isolation level here, not snapshot isolation.
198
+ // The data may change during the transaction, but that is compensated for in the streaming
199
+ // replication afterward.
200
+ const transaction = await this.connections.createTransaction();
201
+ await transaction.begin(sql.ISOLATION_LEVEL.READ_COMMITTED);
202
+ try {
203
+ await this.snapshotTable(batch, transaction, table, limited);
204
+ // Get the current LSN.
205
+ // The data will only be consistent once incremental replication has passed that point.
206
+ // We have to get this LSN _after_ we have finished the table snapshot.
207
+ //
208
+ // There are basically two relevant LSNs here:
209
+ // A: PreSnapshot: The LSN before the snapshot starts.
210
+ // B: PostSnapshot: The LSN after the table snapshot is complete, which is what we get here.
211
+ // When we do the snapshot queries, the data that we get back for each batch could match the state
212
+ // anywhere between A and B. To actually have a consistent state on our side, we need to:
213
+ // 1. Complete the snapshot.
214
+ // 2. Wait until logical replication has caught up with all the changes between A and B.
215
+ // Calling `markSnapshotDone(LSN B)` covers that.
216
+ const postSnapshotLSN = await getLatestLSN(this.connections);
217
+ // Side note: A ROLLBACK would probably also be fine here, since we only read in this transaction.
218
+ await transaction.commit();
219
+ const [updatedSourceTable] = await batch.markSnapshotDone([table.sourceTable], postSnapshotLSN.toString());
220
+ this.tableCache.updateSourceTable(updatedSourceTable);
221
+ }
222
+ catch (e) {
223
+ await transaction.rollback();
224
+ throw e;
225
+ }
226
+ }
227
+ async snapshotTable(batch, transaction, table, limited) {
228
+ let totalEstimatedCount = table.sourceTable.snapshotStatus?.totalEstimatedCount;
229
+ let replicatedCount = table.sourceTable.snapshotStatus?.replicatedCount ?? 0;
230
+ let lastCountTime = 0;
231
+ let query;
232
+ // We do streaming on two levels:
233
+ // 1. Coarse select from the entire table, stream rows 1 by one
234
+ // 2. Fine level: Stream batches of rows with each fetch call
235
+ if (limited) {
236
+ query = new IdSnapshotQuery(transaction, table, limited);
237
+ }
238
+ else if (BatchedSnapshotQuery.supports(table)) {
239
+ // Single primary key - we can use the primary key for chunking
240
+ const orderByKey = table.sourceTable.replicaIdColumns[0];
241
+ query = new BatchedSnapshotQuery(transaction, table, this.snapshotBatchSize, table.sourceTable.snapshotStatus?.lastKey ?? null);
242
+ if (table.sourceTable.snapshotStatus?.lastKey != null) {
243
+ this.logger.info(`Replicating ${table.toQualifiedName()} ${table.sourceTable.formatSnapshotProgress()} - resuming from ${orderByKey.name} > ${query.lastKey}`);
244
+ }
245
+ else {
246
+ this.logger.info(`Replicating ${table.toQualifiedName()} ${table.sourceTable.formatSnapshotProgress()} - resumable`);
247
+ }
248
+ }
249
+ else {
250
+ // Fallback case - query the entire table
251
+ this.logger.info(`Replicating ${table.toQualifiedName()} ${table.sourceTable.formatSnapshotProgress()} - not resumable`);
252
+ query = new SimpleSnapshotQuery(transaction, table);
253
+ replicatedCount = 0;
254
+ }
255
+ await query.initialize();
256
+ let hasRemainingData = true;
257
+ while (hasRemainingData) {
258
+ // Fetch 10k at a time.
259
+ // The balance here is between latency overhead per FETCH call,
260
+ // and not spending too much time on each FETCH call.
261
+ // We aim for a couple of seconds on each FETCH call.
262
+ let batchReplicatedCount = 0;
263
+ let columns = null;
264
+ const cursor = query.next();
265
+ for await (const result of cursor) {
266
+ if (columns == null && isIColumnMetadata(result)) {
267
+ columns = result;
268
+ continue;
269
+ }
270
+ else {
271
+ if (!columns) {
272
+ throw new ReplicationAssertionError(`Missing column metadata`);
273
+ }
274
+ const inputRow = toSqliteInputRow(result, columns);
275
+ const row = this.syncRules.applyRowContext(inputRow);
276
+ // This auto-flushes when the batch reaches its size limit
277
+ await batch.save({
278
+ tag: storage.SaveOperationTag.INSERT,
279
+ sourceTable: table.sourceTable,
280
+ before: undefined,
281
+ beforeReplicaId: undefined,
282
+ after: row,
283
+ afterReplicaId: getUuidReplicaIdentityBson(row, table.sourceTable.replicaIdColumns)
284
+ });
285
+ replicatedCount++;
286
+ batchReplicatedCount++;
287
+ this.metrics.getCounter(ReplicationMetric.ROWS_REPLICATED).add(1);
288
+ }
289
+ this.touch();
290
+ }
291
+ // Important: flush before marking progress
292
+ await batch.flush();
293
+ if (limited == null) {
294
+ let lastKey;
295
+ if (query instanceof BatchedSnapshotQuery) {
296
+ lastKey = query.getLastKeySerialized();
297
+ }
298
+ if (lastCountTime < performance.now() - 10 * 60 * 1000) {
299
+ // Even though we're doing the snapshot inside a transaction, the transaction uses
300
+ // the default "Read Committed" isolation level. This means we can get new data
301
+ // within the transaction, so we re-estimate the count every 10 minutes when replicating
302
+ // large tables.
303
+ totalEstimatedCount = await this.estimatedCountNumber(table, transaction);
304
+ lastCountTime = performance.now();
305
+ }
306
+ const updatedSourceTable = await batch.updateTableProgress(table.sourceTable, {
307
+ lastKey: lastKey,
308
+ replicatedCount: replicatedCount,
309
+ totalEstimatedCount: totalEstimatedCount
310
+ });
311
+ this.tableCache.updateSourceTable(updatedSourceTable);
312
+ this.logger.info(`Replicating ${table.toQualifiedName()} ${table.sourceTable.formatSnapshotProgress()}`);
313
+ }
314
+ else {
315
+ this.logger.info(`Replicating ${table.toQualifiedName()} ${replicatedCount}/${limited.length} for resnapshot`);
316
+ }
317
+ if (this.abortSignal.aborted) {
318
+ // We only abort after flushing
319
+ throw new ReplicationAbortedError(`Initial replication interrupted`);
320
+ }
321
+ // When the batch of rows is smaller than the requested batch size we know it is the final batch
322
+ if (batchReplicatedCount < this.snapshotBatchSize) {
323
+ hasRemainingData = false;
324
+ }
325
+ }
326
+ }
327
+ /**
328
+ * Estimate the number of rows in a table. This query uses partition stats view to get a fast estimate of the row count.
329
+ * This requires that the MSSQL DB user has the VIEW DATABASE PERFORMANCE STATE permission.
330
+ * @param table
331
+ * @param transaction
332
+ */
333
+ async estimatedCountNumber(table, transaction) {
334
+ const request = transaction ? transaction.request() : await this.connections.createRequest();
335
+ const { recordset: result } = await request.query(`SELECT SUM(row_count) AS total_rows
336
+ FROM sys.dm_db_partition_stats
337
+ WHERE object_id = OBJECT_ID('${table.toQualifiedName()}')
338
+ AND index_id < 2;`);
339
+ return result[0].total_rows ?? -1;
340
+ }
341
+ /**
342
+ * Start initial replication.
343
+ *
344
+ * If (partial) replication was done before on this slot, this clears the state
345
+ * and starts again from scratch.
346
+ */
347
+ async startInitialReplication(snapshotStatus) {
348
+ let { status, snapshotLSN } = snapshotStatus;
349
+ if (status === SnapshotStatus.RESTART_REQUIRED) {
350
+ this.logger.info(`Snapshot restart required, clearing state.`);
351
+ // This happens if the last replicated checkpoint LSN is no longer available in the CDC tables.
352
+ await this.storage.clear({ signal: this.abortSignal });
353
+ }
354
+ await this.storage.startBatch({
355
+ logger: this.logger,
356
+ zeroLSN: LSN.ZERO,
357
+ defaultSchema: this.defaultSchema,
358
+ storeCurrentData: false,
359
+ skipExistingRows: true
360
+ }, async (batch) => {
361
+ if (snapshotLSN == null) {
362
+ // First replication attempt - set the snapshot LSN to the current LSN before starting
363
+ snapshotLSN = (await getLatestReplicatedLSN(this.connections)).toString();
364
+ await batch.setResumeLsn(snapshotLSN);
365
+ const latestLSN = (await getLatestLSN(this.connections)).toString();
366
+ this.logger.info(`Marking snapshot at ${snapshotLSN}, Latest DB LSN ${latestLSN}.`);
367
+ }
368
+ else {
369
+ this.logger.info(`Resuming snapshot at ${snapshotLSN}.`);
370
+ }
371
+ const tablesToSnapshot = [];
372
+ for (const table of this.tableCache.getAll()) {
373
+ if (table.sourceTable.snapshotComplete) {
374
+ this.logger.info(`Skipping table [${table.toQualifiedName()}] - snapshot already done.`);
375
+ continue;
376
+ }
377
+ const count = await this.estimatedCountNumber(table);
378
+ const updatedSourceTable = await batch.updateTableProgress(table.sourceTable, {
379
+ totalEstimatedCount: count
380
+ });
381
+ this.tableCache.updateSourceTable(updatedSourceTable);
382
+ tablesToSnapshot.push(table);
383
+ this.logger.info(`To replicate: ${table.toQualifiedName()} ${table.sourceTable.formatSnapshotProgress()}`);
384
+ }
385
+ for (const table of tablesToSnapshot) {
386
+ await this.snapshotTableInTx(batch, table);
387
+ this.touch();
388
+ }
389
+ // This will not create a consistent checkpoint yet, but will persist the op.
390
+ // Actual checkpoint will be created when streaming replication caught up.
391
+ await batch.commit(snapshotLSN);
392
+ this.logger.info(`Snapshot done. Need to replicate from ${snapshotLSN} to ${batch.noCheckpointBeforeLsn} to be consistent`);
393
+ });
394
+ }
395
+ async initReplication() {
396
+ const errors = await checkSourceConfiguration(this.connections);
397
+ if (errors.length > 0) {
398
+ throw new CDCConfigurationError(`CDC Configuration Errors: ${errors.join(', ')}`);
399
+ }
400
+ await this.populateTableCache();
401
+ const snapshotStatus = await this.checkSnapshotStatus();
402
+ if (snapshotStatus.status !== SnapshotStatus.DONE) {
403
+ await this.startInitialReplication(snapshotStatus);
404
+ }
405
+ }
406
+ /**
407
+ * Checks if the initial sync has already been completed and if updates from the last checkpoint are still available
408
+ * in the CDC instances.
409
+ */
410
+ async checkSnapshotStatus() {
411
+ const status = await this.storage.getStatus();
412
+ if (status.snapshot_done && status.checkpoint_lsn) {
413
+ // Snapshot is done, but we still need to check that the last known checkpoint LSN is still
414
+ // within the threshold of the CDC tables
415
+ this.logger.info(`Initial replication already done`);
416
+ const lastCheckpointLSN = LSN.fromString(status.checkpoint_lsn);
417
+ // Check that the CDC tables still have valid data
418
+ const isAvailable = await isWithinRetentionThreshold({
419
+ checkpointLSN: lastCheckpointLSN,
420
+ tables: this.tableCache.getAll(),
421
+ connectionManager: this.connections
422
+ });
423
+ if (!isAvailable) {
424
+ this.logger.warn(`Updates from the last checkpoint are no longer available in the CDC instance, starting initial replication again.`);
425
+ }
426
+ return { status: isAvailable ? SnapshotStatus.DONE : SnapshotStatus.RESTART_REQUIRED, snapshotLSN: null };
427
+ }
428
+ else {
429
+ return { status: SnapshotStatus.IN_PROGRESS, snapshotLSN: status.snapshot_lsn };
430
+ }
431
+ }
432
+ async streamChanges() {
433
+ await this.storage.startBatch({
434
+ logger: this.logger,
435
+ zeroLSN: LSN.ZERO,
436
+ defaultSchema: this.defaultSchema,
437
+ storeCurrentData: false,
438
+ skipExistingRows: false
439
+ }, async (batch) => {
440
+ if (batch.resumeFromLsn == null) {
441
+ throw new ReplicationAssertionError(`No LSN found to resume replication from.`);
442
+ }
443
+ const startLSN = LSN.fromString(batch.resumeFromLsn);
444
+ const sourceTables = this.tableCache.getAll();
445
+ const eventHandler = this.createEventHandler(batch);
446
+ const poller = new CDCPoller({
447
+ connectionManager: this.connections,
448
+ eventHandler,
449
+ sourceTables,
450
+ startLSN,
451
+ pollingOptions: this.options.pollingOptions,
452
+ logger: this.logger
453
+ });
454
+ this.abortSignal.addEventListener('abort', async () => {
455
+ await poller.stop();
456
+ }, { once: true });
457
+ await createCheckpoint(this.connections);
458
+ this.logger.info(`Streaming changes from: ${startLSN}`);
459
+ await poller.replicateUntilStopped();
460
+ });
461
+ }
462
+ createEventHandler(batch) {
463
+ return {
464
+ onInsert: async (row, table, columns) => {
465
+ const afterRow = this.toSqliteRow(row, columns);
466
+ await batch.save({
467
+ tag: storage.SaveOperationTag.INSERT,
468
+ sourceTable: table.sourceTable,
469
+ before: undefined,
470
+ beforeReplicaId: undefined,
471
+ after: afterRow,
472
+ afterReplicaId: getUuidReplicaIdentityBson(afterRow, table.sourceTable.replicaIdColumns)
473
+ });
474
+ this.metrics.getCounter(ReplicationMetric.ROWS_REPLICATED).add(1);
475
+ },
476
+ onUpdate: async (rowAfter, rowBefore, table, columns) => {
477
+ const beforeRow = this.toSqliteRow(rowBefore, columns);
478
+ const afterRow = this.toSqliteRow(rowAfter, columns);
479
+ await batch.save({
480
+ tag: storage.SaveOperationTag.UPDATE,
481
+ sourceTable: table.sourceTable,
482
+ before: beforeRow,
483
+ beforeReplicaId: getUuidReplicaIdentityBson(beforeRow, table.sourceTable.replicaIdColumns),
484
+ after: afterRow,
485
+ afterReplicaId: getUuidReplicaIdentityBson(afterRow, table.sourceTable.replicaIdColumns)
486
+ });
487
+ this.metrics.getCounter(ReplicationMetric.ROWS_REPLICATED).add(1);
488
+ },
489
+ onDelete: async (row, table, columns) => {
490
+ const beforeRow = this.toSqliteRow(row, columns);
491
+ await batch.save({
492
+ tag: storage.SaveOperationTag.DELETE,
493
+ sourceTable: table.sourceTable,
494
+ before: beforeRow,
495
+ beforeReplicaId: getUuidReplicaIdentityBson(beforeRow, table.sourceTable.replicaIdColumns),
496
+ after: undefined,
497
+ afterReplicaId: undefined
498
+ });
499
+ this.metrics.getCounter(ReplicationMetric.ROWS_REPLICATED).add(1);
500
+ },
501
+ onCommit: async (lsn, transactionCount) => {
502
+ await batch.commit(lsn);
503
+ this.metrics.getCounter(ReplicationMetric.TRANSACTIONS_REPLICATED).add(transactionCount);
504
+ this.isStartingReplication = false;
505
+ },
506
+ onSchemaChange: async () => {
507
+ // TODO: Handle schema changes
508
+ }
509
+ };
510
+ }
511
+ /**
512
+ * Convert CDC row data to SqliteRow format.
513
+ * CDC rows include table columns plus CDC metadata columns (__$operation, __$start_lsn, etc.).
514
+ * We filter out the CDC metadata columns.
515
+ */
516
+ toSqliteRow(row, columns) {
517
+ const inputRow = CDCToSqliteRow({ row, columns });
518
+ return this.syncRules.applyRowContext(inputRow);
519
+ }
520
+ async getReplicationLagMillis() {
521
+ if (this.oldestUncommittedChange == null) {
522
+ if (this.isStartingReplication) {
523
+ // We don't have anything to compute replication lag with yet.
524
+ return undefined;
525
+ }
526
+ else {
527
+ // We don't have any uncommitted changes, so replication is up-to-date.
528
+ return 0;
529
+ }
530
+ }
531
+ return Date.now() - this.oldestUncommittedChange.getTime();
532
+ }
533
+ touch() {
534
+ container.probes.touch().catch((e) => {
535
+ this.logger.error(`Error touching probe`, e);
536
+ });
537
+ }
538
+ }
539
+ //# sourceMappingURL=CDCStream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CDCStream.js","sourceRoot":"","sources":["../../src/replication/CDCStream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { BaseObserver } from '@powersync/lib-services-framework';
2
+ import sql from 'mssql';
3
+ import { NormalizedMSSQLConnectionConfig } from '../types/types.js';
4
+ import { MSSQLParameter } from '../types/mssql-data-types.js';
5
+ export declare const DEFAULT_SCHEMA = "dbo";
6
+ export interface MSSQLConnectionManagerListener {
7
+ onEnded(): void;
8
+ }
9
+ export declare class MSSQLConnectionManager extends BaseObserver<MSSQLConnectionManagerListener> {
10
+ options: NormalizedMSSQLConnectionConfig;
11
+ private readonly pool;
12
+ constructor(options: NormalizedMSSQLConnectionConfig, poolOptions: sql.PoolOpts<sql.Connection>);
13
+ get connectionTag(): string;
14
+ get connectionId(): string;
15
+ get databaseName(): string;
16
+ get schema(): string;
17
+ private ensureConnected;
18
+ createTransaction(): Promise<sql.Transaction>;
19
+ createRequest(): Promise<sql.Request>;
20
+ query(query: string, parameters?: MSSQLParameter[]): Promise<sql.IResult<any>>;
21
+ execute(procedure: string, parameters?: MSSQLParameter[]): Promise<sql.IProcedureResult<any>>;
22
+ end(): Promise<void>;
23
+ }