@powersync/service-module-mssql 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/LICENSE +67 -0
  2. package/README.md +3 -0
  3. package/ci/init-mssql.sql +50 -0
  4. package/dist/api/MSSQLRouteAPIAdapter.d.ts +21 -0
  5. package/dist/api/MSSQLRouteAPIAdapter.js +248 -0
  6. package/dist/api/MSSQLRouteAPIAdapter.js.map +1 -0
  7. package/dist/common/LSN.d.ts +37 -0
  8. package/dist/common/LSN.js +64 -0
  9. package/dist/common/LSN.js.map +1 -0
  10. package/dist/common/MSSQLSourceTable.d.ts +27 -0
  11. package/dist/common/MSSQLSourceTable.js +35 -0
  12. package/dist/common/MSSQLSourceTable.js.map +1 -0
  13. package/dist/common/MSSQLSourceTableCache.d.ts +14 -0
  14. package/dist/common/MSSQLSourceTableCache.js +28 -0
  15. package/dist/common/MSSQLSourceTableCache.js.map +1 -0
  16. package/dist/common/mssqls-to-sqlite.d.ts +18 -0
  17. package/dist/common/mssqls-to-sqlite.js +143 -0
  18. package/dist/common/mssqls-to-sqlite.js.map +1 -0
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.js +2 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/module/MSSQLModule.d.ts +15 -0
  23. package/dist/module/MSSQLModule.js +68 -0
  24. package/dist/module/MSSQLModule.js.map +1 -0
  25. package/dist/replication/CDCPoller.d.ts +67 -0
  26. package/dist/replication/CDCPoller.js +183 -0
  27. package/dist/replication/CDCPoller.js.map +1 -0
  28. package/dist/replication/CDCReplicationJob.d.ts +17 -0
  29. package/dist/replication/CDCReplicationJob.js +76 -0
  30. package/dist/replication/CDCReplicationJob.js.map +1 -0
  31. package/dist/replication/CDCReplicator.d.ts +18 -0
  32. package/dist/replication/CDCReplicator.js +55 -0
  33. package/dist/replication/CDCReplicator.js.map +1 -0
  34. package/dist/replication/CDCStream.d.ts +106 -0
  35. package/dist/replication/CDCStream.js +536 -0
  36. package/dist/replication/CDCStream.js.map +1 -0
  37. package/dist/replication/MSSQLConnectionManager.d.ts +23 -0
  38. package/dist/replication/MSSQLConnectionManager.js +97 -0
  39. package/dist/replication/MSSQLConnectionManager.js.map +1 -0
  40. package/dist/replication/MSSQLConnectionManagerFactory.d.ts +10 -0
  41. package/dist/replication/MSSQLConnectionManagerFactory.js +28 -0
  42. package/dist/replication/MSSQLConnectionManagerFactory.js.map +1 -0
  43. package/dist/replication/MSSQLErrorRateLimiter.d.ts +10 -0
  44. package/dist/replication/MSSQLErrorRateLimiter.js +34 -0
  45. package/dist/replication/MSSQLErrorRateLimiter.js.map +1 -0
  46. package/dist/replication/MSSQLSnapshotQuery.d.ts +71 -0
  47. package/dist/replication/MSSQLSnapshotQuery.js +190 -0
  48. package/dist/replication/MSSQLSnapshotQuery.js.map +1 -0
  49. package/dist/types/mssql-data-types.d.ts +66 -0
  50. package/dist/types/mssql-data-types.js +62 -0
  51. package/dist/types/mssql-data-types.js.map +1 -0
  52. package/dist/types/types.d.ts +177 -0
  53. package/dist/types/types.js +141 -0
  54. package/dist/types/types.js.map +1 -0
  55. package/dist/utils/mssql.d.ts +80 -0
  56. package/dist/utils/mssql.js +329 -0
  57. package/dist/utils/mssql.js.map +1 -0
  58. package/dist/utils/schema.d.ts +21 -0
  59. package/dist/utils/schema.js +131 -0
  60. package/dist/utils/schema.js.map +1 -0
  61. package/package.json +51 -0
  62. package/src/api/MSSQLRouteAPIAdapter.ts +283 -0
  63. package/src/common/LSN.ts +77 -0
  64. package/src/common/MSSQLSourceTable.ts +54 -0
  65. package/src/common/MSSQLSourceTableCache.ts +36 -0
  66. package/src/common/mssqls-to-sqlite.ts +151 -0
  67. package/src/index.ts +1 -0
  68. package/src/module/MSSQLModule.ts +82 -0
  69. package/src/replication/CDCPoller.ts +241 -0
  70. package/src/replication/CDCReplicationJob.ts +87 -0
  71. package/src/replication/CDCReplicator.ts +70 -0
  72. package/src/replication/CDCStream.ts +688 -0
  73. package/src/replication/MSSQLConnectionManager.ts +113 -0
  74. package/src/replication/MSSQLConnectionManagerFactory.ts +33 -0
  75. package/src/replication/MSSQLErrorRateLimiter.ts +36 -0
  76. package/src/replication/MSSQLSnapshotQuery.ts +230 -0
  77. package/src/types/mssql-data-types.ts +79 -0
  78. package/src/types/types.ts +224 -0
  79. package/src/utils/mssql.ts +420 -0
  80. package/src/utils/schema.ts +172 -0
  81. package/test/src/CDCStream.test.ts +206 -0
  82. package/test/src/CDCStreamTestContext.ts +212 -0
  83. package/test/src/CDCStream_resumable_snapshot.test.ts +152 -0
  84. package/test/src/env.ts +11 -0
  85. package/test/src/mssql-to-sqlite.test.ts +474 -0
  86. package/test/src/setup.ts +12 -0
  87. package/test/src/util.ts +189 -0
  88. package/test/tsconfig.json +28 -0
  89. package/test/tsconfig.tsbuildinfo +1 -0
  90. package/tsconfig.json +26 -0
  91. package/tsconfig.tsbuildinfo +1 -0
  92. package/vitest.config.ts +15 -0
@@ -0,0 +1,55 @@
1
+ import { replication } from '@powersync/service-core';
2
+ import { CDCReplicationJob } from './CDCReplicationJob.js';
3
+ import { MSSQLModule } from '../module/MSSQLModule.js';
4
+ export class CDCReplicator extends replication.AbstractReplicator {
5
+ connectionFactory;
6
+ cdcReplicatorOptions;
7
+ constructor(options) {
8
+ super(options);
9
+ this.connectionFactory = options.connectionFactory;
10
+ this.cdcReplicatorOptions = options;
11
+ }
12
+ createJob(options) {
13
+ return new CDCReplicationJob({
14
+ id: this.createJobId(options.storage.group_id),
15
+ storage: options.storage,
16
+ metrics: this.metrics,
17
+ lock: options.lock,
18
+ connectionFactory: this.connectionFactory,
19
+ rateLimiter: this.rateLimiter,
20
+ pollingOptions: this.cdcReplicatorOptions.pollingOptions
21
+ });
22
+ }
23
+ async cleanUp(syncRulesStorage) { }
24
+ async stop() {
25
+ await super.stop();
26
+ await this.connectionFactory.shutdown();
27
+ }
28
+ async testConnection() {
29
+ return await MSSQLModule.testConnection(this.connectionFactory.connectionConfig);
30
+ }
31
+ async getReplicationLagMillis() {
32
+ // TODO:Get replication lag
33
+ const lag = await super.getReplicationLagMillis();
34
+ if (lag != null) {
35
+ return lag;
36
+ }
37
+ // Booting or in an error loop. Check last active replication status.
38
+ // This includes sync rules in an ERROR state.
39
+ const content = await this.storage.getActiveSyncRulesContent();
40
+ if (content == null) {
41
+ return undefined;
42
+ }
43
+ // Measure the lag from the last commit or keepalive timestamp.
44
+ // This is not 100% accurate since it is the commit time in the storage db rather than
45
+ // the source db, but it's the best we currently have for mssql.
46
+ const checkpointTs = content.last_checkpoint_ts?.getTime() ?? 0;
47
+ const keepaliveTs = content.last_keepalive_ts?.getTime() ?? 0;
48
+ const latestTs = Math.max(checkpointTs, keepaliveTs);
49
+ if (latestTs != 0) {
50
+ return Date.now() - latestTs;
51
+ }
52
+ return undefined;
53
+ }
54
+ }
55
+ //# sourceMappingURL=CDCReplicator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CDCReplicator.js","sourceRoot":"","sources":["../../src/replication/CDCReplicator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAW,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAQvD,MAAM,OAAO,aAAc,SAAQ,WAAW,CAAC,kBAAqC;IACjE,iBAAiB,CAAgC;IACjD,oBAAoB,CAAuB;IAE5D,YAAY,OAA6B;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;QACnD,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC;IACtC,CAAC;IAED,SAAS,CAAC,OAAqC;QAC7C,OAAO,IAAI,iBAAiB,CAAC;YAC3B,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC9C,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,cAAc,EAAE,IAAI,CAAC,oBAAoB,CAAC,cAAc;SACzD,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,gBAAgD,IAAkB,CAAC;IAEjF,KAAK,CAAC,IAAI;QACR,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,OAAO,MAAM,WAAW,CAAC,cAAc,CAAC,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IACnF,CAAC;IAED,KAAK,CAAC,uBAAuB;QAC3B,2BAA2B;QAC3B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,uBAAuB,EAAE,CAAC;QAClD,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC;QACb,CAAC;QAED,qEAAqE;QACrE,8CAA8C;QAC9C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,yBAAyB,EAAE,CAAC;QAC/D,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACpB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,+DAA+D;QAC/D,sFAAsF;QACtF,gEAAgE;QAChE,MAAM,YAAY,GAAG,OAAO,CAAC,kBAAkB,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAChE,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;QACrD,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC;QAC/B,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,106 @@
1
+ import { DatabaseConnectionError, Logger } from '@powersync/lib-services-framework';
2
+ import { MetricsEngine, SourceEntityDescriptor, storage } from '@powersync/service-core';
3
+ import { TablePattern } from '@powersync/service-sync-rules';
4
+ import { MSSQLConnectionManager } from './MSSQLConnectionManager.js';
5
+ import sql from 'mssql';
6
+ import { MSSQLSourceTable } from '../common/MSSQLSourceTable.js';
7
+ import { CDCPollingOptions } from '../types/types.js';
8
+ export interface CDCStreamOptions {
9
+ connections: MSSQLConnectionManager;
10
+ storage: storage.SyncRulesBucketStorage;
11
+ metrics: MetricsEngine;
12
+ abortSignal: AbortSignal;
13
+ logger?: Logger;
14
+ /**
15
+ * Override snapshot batch size for testing.
16
+ * Defaults to 10_000.
17
+ * Note that queries are streamed, so we don't keep that much data in memory.
18
+ */
19
+ snapshotBatchSize?: number;
20
+ pollingOptions: CDCPollingOptions;
21
+ }
22
+ export declare enum SnapshotStatus {
23
+ IN_PROGRESS = "in-progress",
24
+ DONE = "done",
25
+ RESTART_REQUIRED = "restart-required"
26
+ }
27
+ export interface SnapshotStatusResult {
28
+ status: SnapshotStatus;
29
+ snapshotLSN: string | null;
30
+ }
31
+ export declare class CDCConfigurationError extends Error {
32
+ constructor(message: string);
33
+ }
34
+ /**
35
+ * Thrown when required updates in the CDC instance tables are no longer available
36
+ *
37
+ * Possible reasons:
38
+ * * Older data has been cleaned up due to exceeding the retention period.
39
+ * This can happen if PowerSync was stopped for a long period of time.
40
+ */
41
+ export declare class CDCDataExpiredError extends DatabaseConnectionError {
42
+ constructor(message: string, cause: any);
43
+ }
44
+ export declare class CDCStream {
45
+ private options;
46
+ private readonly syncRules;
47
+ private readonly storage;
48
+ private readonly connections;
49
+ private readonly abortSignal;
50
+ private readonly logger;
51
+ private tableCache;
52
+ /**
53
+ * Time of the oldest uncommitted change, according to the source db.
54
+ * This is used to determine the replication lag.
55
+ */
56
+ private oldestUncommittedChange;
57
+ /**
58
+ * Keep track of whether we have done a commit or keepalive yet.
59
+ * We can only compute replication lag if isStartingReplication == false, or oldestUncommittedChange is present.
60
+ */
61
+ isStartingReplication: boolean;
62
+ constructor(options: CDCStreamOptions);
63
+ private get metrics();
64
+ get stopped(): boolean;
65
+ get defaultSchema(): string;
66
+ get groupId(): number;
67
+ get connectionId(): number;
68
+ get connectionTag(): string;
69
+ get snapshotBatchSize(): number;
70
+ replicate(): Promise<void>;
71
+ populateTableCache(): Promise<void>;
72
+ getQualifiedTableNames(batch: storage.BucketStorageBatch, tablePattern: TablePattern): Promise<MSSQLSourceTable[]>;
73
+ processTable(batch: storage.BucketStorageBatch, table: SourceEntityDescriptor, snapshot: boolean): Promise<MSSQLSourceTable>;
74
+ private snapshotTableInTx;
75
+ private snapshotTable;
76
+ /**
77
+ * Estimate the number of rows in a table. This query uses partition stats view to get a fast estimate of the row count.
78
+ * This requires that the MSSQL DB user has the VIEW DATABASE PERFORMANCE STATE permission.
79
+ * @param table
80
+ * @param transaction
81
+ */
82
+ estimatedCountNumber(table: MSSQLSourceTable, transaction?: sql.Transaction): Promise<number>;
83
+ /**
84
+ * Start initial replication.
85
+ *
86
+ * If (partial) replication was done before on this slot, this clears the state
87
+ * and starts again from scratch.
88
+ */
89
+ startInitialReplication(snapshotStatus: SnapshotStatusResult): Promise<void>;
90
+ initReplication(): Promise<void>;
91
+ /**
92
+ * Checks if the initial sync has already been completed and if updates from the last checkpoint are still available
93
+ * in the CDC instances.
94
+ */
95
+ private checkSnapshotStatus;
96
+ streamChanges(): Promise<void>;
97
+ private createEventHandler;
98
+ /**
99
+ * Convert CDC row data to SqliteRow format.
100
+ * CDC rows include table columns plus CDC metadata columns (__$operation, __$start_lsn, etc.).
101
+ * We filter out the CDC metadata columns.
102
+ */
103
+ private toSqliteRow;
104
+ getReplicationLagMillis(): Promise<number | undefined>;
105
+ private touch;
106
+ }