@powersync/service-module-mssql 0.0.0-dev-20260602073133 → 0.0.0-dev-20260909133214
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +209 -4
- package/dist/api/MSSQLRouteAPIAdapter.d.ts +4 -5
- package/dist/api/MSSQLRouteAPIAdapter.js +33 -39
- package/dist/api/MSSQLRouteAPIAdapter.js.map +1 -1
- package/dist/common/MSSQLSourceTable.d.ts +12 -2
- package/dist/common/MSSQLSourceTable.js +30 -4
- package/dist/common/MSSQLSourceTable.js.map +1 -1
- package/dist/module/MSSQLModule.js +2 -1
- package/dist/module/MSSQLModule.js.map +1 -1
- package/dist/replication/CDCPoller.d.ts +13 -36
- package/dist/replication/CDCPoller.js +173 -129
- package/dist/replication/CDCPoller.js.map +1 -1
- package/dist/replication/CDCReplicationJob.js +1 -1
- package/dist/replication/CDCReplicationJob.js.map +1 -1
- package/dist/replication/CDCReplicator.js +1 -1
- package/dist/replication/CDCReplicator.js.map +1 -1
- package/dist/replication/CDCStream.d.ts +11 -14
- package/dist/replication/CDCStream.js +124 -115
- package/dist/replication/CDCStream.js.map +1 -1
- package/dist/replication/CaptureReconciler.d.ts +47 -0
- package/dist/replication/CaptureReconciler.js +155 -0
- package/dist/replication/CaptureReconciler.js.map +1 -0
- package/dist/replication/MSSQLConnectionManager.d.ts +1 -0
- package/dist/replication/MSSQLConnectionManager.js +19 -14
- package/dist/replication/MSSQLConnectionManager.js.map +1 -1
- package/dist/replication/MSSQLTableReconciliationContext.d.ts +21 -0
- package/dist/replication/MSSQLTableReconciliationContext.js +7 -0
- package/dist/replication/MSSQLTableReconciliationContext.js.map +1 -0
- package/dist/replication/SchemaChange.d.ts +67 -0
- package/dist/replication/SchemaChange.js +31 -0
- package/dist/replication/SchemaChange.js.map +1 -0
- package/dist/types/types.d.ts +13 -0
- package/dist/types/types.js +28 -2
- package/dist/types/types.js.map +1 -1
- package/dist/utils/mssql.js +1 -1
- package/dist/utils/schema.d.ts +14 -1
- package/dist/utils/schema.js +43 -45
- package/dist/utils/schema.js.map +1 -1
- package/package.json +11 -21
- package/src/api/MSSQLRouteAPIAdapter.ts +38 -49
- package/src/common/MSSQLSourceTable.ts +32 -4
- package/src/module/MSSQLModule.ts +2 -1
- package/src/replication/CDCPoller.ts +206 -162
- package/src/replication/CDCReplicationJob.ts +1 -1
- package/src/replication/CDCReplicator.ts +1 -1
- package/src/replication/CDCStream.ts +157 -163
- package/src/replication/CaptureReconciler.ts +186 -0
- package/src/replication/MSSQLConnectionManager.ts +23 -14
- package/src/replication/MSSQLTableReconciliationContext.ts +29 -0
- package/src/replication/SchemaChange.ts +79 -0
- package/src/types/types.ts +47 -2
- package/src/utils/mssql.ts +1 -1
- package/src/utils/schema.ts +60 -54
- package/test/src/CDCPoller.test.ts +382 -0
- package/test/src/CDCStream.test.ts +6 -2
- package/test/src/CDCStreamTestContext.ts +30 -23
- package/test/src/CaptureReconciler.test.ts +171 -0
- package/test/src/MSSQLSourceTable.test.ts +30 -0
- package/test/src/config.test.ts +71 -0
- package/test/src/schema-changes.test.ts +513 -249
- package/test/src/schema.test.ts +17 -0
- package/test/src/util.ts +73 -9
- package/tsconfig.json +0 -3
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { ErrorCode, ReplicationAssertionError, ServiceError } from '@powersync/lib-services-framework';
|
|
2
|
+
import { storage } from '@powersync/service-core';
|
|
3
|
+
import * as t from 'ts-codec';
|
|
4
|
+
import { toQualifiedTableName } from '../utils/mssql.js';
|
|
5
|
+
import { MSSQLTableReconciliationState } from './MSSQLTableReconciliationContext.js';
|
|
6
|
+
/**
|
|
7
|
+
* The pinned capture instance was dropped and cannot be replaced in this stream.
|
|
8
|
+
*/
|
|
9
|
+
export class CaptureInstanceMissingError extends ServiceError {
|
|
10
|
+
constructor(message) {
|
|
11
|
+
super(ErrorCode.PSYNC_S1601, message);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A configured table does not exist or does not have CDC enabled yet.
|
|
16
|
+
*/
|
|
17
|
+
export class SourceTableNotReadyError extends ServiceError {
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(ErrorCode.PSYNC_S1602, message);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A replicated table is unavailable or no longer matches its persisted source binding.
|
|
24
|
+
*/
|
|
25
|
+
export class SourceTableUnavailableError extends ServiceError {
|
|
26
|
+
constructor(message) {
|
|
27
|
+
super(ErrorCode.PSYNC_S1603, message);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Persisted capture-table identity. Names are not enough because SQL Server can reuse them.
|
|
32
|
+
*/
|
|
33
|
+
export const MSSQLSourceMetadata = t.object({
|
|
34
|
+
captureTableObjectId: t.number
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Parse persisted capture metadata, returning null for legacy records.
|
|
38
|
+
*/
|
|
39
|
+
export function readCaptureMetadata(value) {
|
|
40
|
+
if (value == null) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
return MSSQLSourceMetadata.decode(value);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Reconcile a discovered source-table state against persisted bindings. Ready tables reconcile
|
|
47
|
+
* against capture instances ordered newest first. New and legacy bindings use the newest instance;
|
|
48
|
+
* pinned bindings keep their instance or fail if it is gone.
|
|
49
|
+
*/
|
|
50
|
+
export function createCaptureReconciler(context) {
|
|
51
|
+
return (({ source, candidates }) => {
|
|
52
|
+
if (context.state === MSSQLTableReconciliationState.TABLE_MISSING) {
|
|
53
|
+
if (candidates.length > 0) {
|
|
54
|
+
// The table is missing, but we already recorded it. Display the corresponding error.
|
|
55
|
+
throw sourceTableUnavailableError(source);
|
|
56
|
+
}
|
|
57
|
+
throw new SourceTableNotReadyError(`Source table ${toQualifiedTableName(source.schema, source.name)} from the sync configuration does not ` +
|
|
58
|
+
`exist. Create the table and enable CDC for it.`);
|
|
59
|
+
}
|
|
60
|
+
// Apply capture pinning after the shared identity check.
|
|
61
|
+
const compatible = [];
|
|
62
|
+
const incompatibleTables = [];
|
|
63
|
+
for (const candidate of candidates) {
|
|
64
|
+
if (storage.sourceIdentityCompatible(source, candidate)) {
|
|
65
|
+
compatible.push(candidate);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
incompatibleTables.push(candidate);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (compatible.length === 0) {
|
|
72
|
+
if (candidates.length > 0) {
|
|
73
|
+
// An overlapping persisted binding with a different source identity is not a new table.
|
|
74
|
+
// This can happen when a table is dropped and recreated while replication is stopped.
|
|
75
|
+
// Reusing the old snapshot or replacing it during a normal job restart would silently
|
|
76
|
+
// adopt a different physical table without a sync config deployment boundary.
|
|
77
|
+
throw sourceTableUnavailableError(source);
|
|
78
|
+
}
|
|
79
|
+
if (context.state === MSSQLTableReconciliationState.CDC_DISABLED) {
|
|
80
|
+
throw new SourceTableNotReadyError(`CDC is not enabled for source table ${toQualifiedTableName(source.schema, source.name)}, which ` +
|
|
81
|
+
`matches the sync configuration. Enable CDC for this table to start replicating it.`);
|
|
82
|
+
}
|
|
83
|
+
// Pin a new binding to the newest instance.
|
|
84
|
+
const newest = context.captureInstances[0];
|
|
85
|
+
return {
|
|
86
|
+
compatibleTables: [],
|
|
87
|
+
incompatibleTables,
|
|
88
|
+
newTableValues: { sourceMetadata: captureMetadata(newest.objectId) }
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
// At least one compatible candidate anchors this process to the discovered source identity.
|
|
92
|
+
// Any remaining incompatible candidates are stale overlapping records, so storage may remove
|
|
93
|
+
// them without adopting a replacement table or changing the binding this process uses.
|
|
94
|
+
if (context.state === MSSQLTableReconciliationState.CDC_DISABLED) {
|
|
95
|
+
throw new CaptureInstanceMissingError(`CDC is no longer enabled for source table ${toQualifiedTableName(source.schema, source.name)}. ` +
|
|
96
|
+
`Re-enable CDC, then redeploy the sync config to adopt the replacement capture instance. Its ` +
|
|
97
|
+
`already-replicated data is retained until the redeployed sync config becomes active.`);
|
|
98
|
+
}
|
|
99
|
+
const availableInstances = context.captureInstances;
|
|
100
|
+
const pinnedObjectIds = new Set();
|
|
101
|
+
let metadataFreeCount = 0;
|
|
102
|
+
for (const candidate of compatible) {
|
|
103
|
+
const metadata = readCaptureMetadata(candidate.sourceMetadata);
|
|
104
|
+
if (metadata == null) {
|
|
105
|
+
metadataFreeCount += 1;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
pinnedObjectIds.add(metadata.captureTableObjectId);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Never guess which capture schema existing snapshots belong to.
|
|
112
|
+
if (pinnedObjectIds.size > 0 && metadataFreeCount > 0) {
|
|
113
|
+
throw new ReplicationAssertionError(`Source table ${toQualifiedTableName(source.schema, source.name)} has a mixture of legacy (metadata-free) and ` +
|
|
114
|
+
`capture-instance-pinned records. This is invalid persisted state.`);
|
|
115
|
+
}
|
|
116
|
+
// All records for a physical table must use the same capture instance.
|
|
117
|
+
if (pinnedObjectIds.size > 1) {
|
|
118
|
+
throw new ReplicationAssertionError(`Source table ${toQualifiedTableName(source.schema, source.name)} has multiple persisted capture identities ` +
|
|
119
|
+
`(${[...pinnedObjectIds].join(', ')}). This is invalid persisted state.`);
|
|
120
|
+
}
|
|
121
|
+
if (pinnedObjectIds.size === 0) {
|
|
122
|
+
// Backfill legacy records with the instance the old code would have selected.
|
|
123
|
+
const newest = availableInstances[0];
|
|
124
|
+
const sourceMetadata = captureMetadata(newest.objectId);
|
|
125
|
+
return {
|
|
126
|
+
compatibleTables: compatible.map((candidate) => candidate.withSourceMetadata(sourceMetadata)),
|
|
127
|
+
incompatibleTables,
|
|
128
|
+
newTableValues: { sourceMetadata }
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const [captureTableObjectId] = [...pinnedObjectIds];
|
|
132
|
+
const available = availableInstances.some((instance) => instance.objectId === captureTableObjectId);
|
|
133
|
+
if (!available) {
|
|
134
|
+
// A replacement may capture a different schema, so do not adopt it in place.
|
|
135
|
+
throw new CaptureInstanceMissingError(`The CDC capture instance (object id ${captureTableObjectId}) for source table ` +
|
|
136
|
+
`${toQualifiedTableName(source.schema, source.name)} is no longer available. Deploy a new sync config to ` +
|
|
137
|
+
`replicate this table against a new capture instance.`);
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
compatibleTables: compatible,
|
|
141
|
+
incompatibleTables,
|
|
142
|
+
newTableValues: { sourceMetadata: captureMetadata(captureTableObjectId) }
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function captureMetadata(captureTableObjectId) {
|
|
147
|
+
return { captureTableObjectId };
|
|
148
|
+
}
|
|
149
|
+
function sourceTableUnavailableError(source) {
|
|
150
|
+
return new SourceTableUnavailableError(`Table ${toQualifiedTableName(source.schema, source.name)} no longer matches the source table binding ` +
|
|
151
|
+
`selected by this replication process. It may have been dropped and recreated, renamed, or had its ` +
|
|
152
|
+
`replication identity changed. Redeploy the sync config to adopt the replacement. Its already-replicated ` +
|
|
153
|
+
`data is retained until the redeployed sync config becomes active.`);
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=CaptureReconciler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CaptureReconciler.js","sourceRoot":"","sources":["../../src/replication/CaptureReconciler.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ export declare const DEFAULT_SCHEMA = "dbo";
|
|
|
6
6
|
export interface MSSQLConnectionManagerListener {
|
|
7
7
|
onEnded(): void;
|
|
8
8
|
}
|
|
9
|
+
export declare function createConnectionPoolConfig(options: NormalizedMSSQLConnectionConfig, poolOptions: sql.PoolOpts<sql.Connection>): sql.config;
|
|
9
10
|
export declare class MSSQLConnectionManager extends BaseObserver<MSSQLConnectionManagerListener> {
|
|
10
11
|
options: NormalizedMSSQLConnectionConfig;
|
|
11
12
|
private readonly pool;
|
|
@@ -3,6 +3,24 @@ import { POWERSYNC_VERSION } from '@powersync/service-core';
|
|
|
3
3
|
import sql from 'mssql';
|
|
4
4
|
import { addParameters } from '../utils/mssql.js';
|
|
5
5
|
export const DEFAULT_SCHEMA = 'dbo';
|
|
6
|
+
export function createConnectionPoolConfig(options, poolOptions) {
|
|
7
|
+
return {
|
|
8
|
+
authentication: options.authentication,
|
|
9
|
+
user: options.username,
|
|
10
|
+
password: options.password,
|
|
11
|
+
server: options.hostname,
|
|
12
|
+
port: options.port,
|
|
13
|
+
database: options.database,
|
|
14
|
+
pool: poolOptions,
|
|
15
|
+
options: {
|
|
16
|
+
appName: `powersync/${POWERSYNC_VERSION}`,
|
|
17
|
+
encrypt: true, // Required for Azure
|
|
18
|
+
trustServerCertificate: options.additionalConfig.trustServerCertificate,
|
|
19
|
+
...(options.tls_servername ? { serverName: options.tls_servername } : {}),
|
|
20
|
+
...(options.cacert ? { cryptoCredentialsDetails: { ca: options.cacert } } : {})
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
6
24
|
export class MSSQLConnectionManager extends BaseObserver {
|
|
7
25
|
options;
|
|
8
26
|
pool;
|
|
@@ -10,20 +28,7 @@ export class MSSQLConnectionManager extends BaseObserver {
|
|
|
10
28
|
super();
|
|
11
29
|
this.options = options;
|
|
12
30
|
// The pool is lazy - no connections are opened until a query is performed.
|
|
13
|
-
this.pool = new sql.ConnectionPool(
|
|
14
|
-
authentication: options.authentication,
|
|
15
|
-
user: options.username,
|
|
16
|
-
password: options.password,
|
|
17
|
-
server: options.hostname,
|
|
18
|
-
port: options.port,
|
|
19
|
-
database: options.database,
|
|
20
|
-
pool: poolOptions,
|
|
21
|
-
options: {
|
|
22
|
-
appName: `powersync/${POWERSYNC_VERSION}`,
|
|
23
|
-
encrypt: true, // Required for Azure
|
|
24
|
-
trustServerCertificate: options.additionalConfig.trustServerCertificate
|
|
25
|
-
}
|
|
26
|
-
});
|
|
31
|
+
this.pool = new sql.ConnectionPool(createConnectionPoolConfig(options, poolOptions));
|
|
27
32
|
}
|
|
28
33
|
get connectionTag() {
|
|
29
34
|
return this.options.tag;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MSSQLConnectionManager.js","sourceRoot":"","sources":["../../src/replication/MSSQLConnectionManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,GAAG,MAAM,OAAO,CAAC;AAGxB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC;AAMpC,MAAM,
|
|
1
|
+
{"version":3,"file":"MSSQLConnectionManager.js","sourceRoot":"","sources":["../../src/replication/MSSQLConnectionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { SourceEntityDescriptor } from '@powersync/service-core';
|
|
2
|
+
import type { CaptureInstance } from '../common/CaptureInstance.js';
|
|
3
|
+
export declare enum MSSQLTableReconciliationState {
|
|
4
|
+
TABLE_MISSING = "table_missing",
|
|
5
|
+
CDC_DISABLED = "cdc_disabled",
|
|
6
|
+
READY = "ready"
|
|
7
|
+
}
|
|
8
|
+
interface BaseMSSQLTableReconciliationContext {
|
|
9
|
+
source: SourceEntityDescriptor;
|
|
10
|
+
}
|
|
11
|
+
export type MSSQLUnavailableTableReconciliationContext = (BaseMSSQLTableReconciliationContext & {
|
|
12
|
+
state: MSSQLTableReconciliationState.TABLE_MISSING;
|
|
13
|
+
}) | (BaseMSSQLTableReconciliationContext & {
|
|
14
|
+
state: MSSQLTableReconciliationState.CDC_DISABLED;
|
|
15
|
+
});
|
|
16
|
+
export type MSSQLReadyTableReconciliationContext = BaseMSSQLTableReconciliationContext & {
|
|
17
|
+
state: MSSQLTableReconciliationState.READY;
|
|
18
|
+
captureInstances: readonly CaptureInstance[];
|
|
19
|
+
};
|
|
20
|
+
export type MSSQLTableReconciliationContext = MSSQLUnavailableTableReconciliationContext | MSSQLReadyTableReconciliationContext;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export var MSSQLTableReconciliationState;
|
|
2
|
+
(function (MSSQLTableReconciliationState) {
|
|
3
|
+
MSSQLTableReconciliationState["TABLE_MISSING"] = "table_missing";
|
|
4
|
+
MSSQLTableReconciliationState["CDC_DISABLED"] = "cdc_disabled";
|
|
5
|
+
MSSQLTableReconciliationState["READY"] = "ready";
|
|
6
|
+
})(MSSQLTableReconciliationState || (MSSQLTableReconciliationState = {}));
|
|
7
|
+
//# sourceMappingURL=MSSQLTableReconciliationContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MSSQLTableReconciliationContext.js","sourceRoot":"","sources":["../../src/replication/MSSQLTableReconciliationContext.ts"],"names":[],"mappings":"AAGA,MAAM,CAAN,IAAY,6BAIX;AAJD,WAAY,6BAA6B;IACvC,gEAA+B,CAAA;IAC/B,8DAA6B,CAAA;IAC7B,gDAAe,CAAA;AACjB,CAAC,EAJW,6BAA6B,KAA7B,6BAA6B,QAIxC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { CaptureInstance } from '../common/CaptureInstance.js';
|
|
2
|
+
import { MSSQLSourceTable } from '../common/MSSQLSourceTable.js';
|
|
3
|
+
import { SourceTableChangeRef } from '../utils/schema.js';
|
|
4
|
+
/**
|
|
5
|
+
* Schema changes are detected to warn or error on, not applied automatically. Polling cannot be
|
|
6
|
+
* made atomic with a commit, so the replicated schema stays fixed until the next deploy.
|
|
7
|
+
*
|
|
8
|
+
* Drops and renames fail the job because they have no known LSN. Continuing could skip unread
|
|
9
|
+
* changes. Existing replicated data is kept for the next deploy to clean up.
|
|
10
|
+
*/
|
|
11
|
+
export declare enum SchemaChangeType {
|
|
12
|
+
/**
|
|
13
|
+
* A replicated table was renamed.
|
|
14
|
+
*/
|
|
15
|
+
TABLE_RENAME = "table_rename",
|
|
16
|
+
/**
|
|
17
|
+
* A replicated table was dropped.
|
|
18
|
+
*/
|
|
19
|
+
TABLE_DROP = "table_drop",
|
|
20
|
+
/**
|
|
21
|
+
* The source columns changed. The pinned capture schema remains active.
|
|
22
|
+
*/
|
|
23
|
+
TABLE_COLUMN_CHANGES = "table_column_changes",
|
|
24
|
+
/**
|
|
25
|
+
* A newer capture instance exists, but the pinned one is still available.
|
|
26
|
+
*/
|
|
27
|
+
NEW_CAPTURE_INSTANCE = "new_capture_instance",
|
|
28
|
+
/**
|
|
29
|
+
* The pinned capture instance is no longer available.
|
|
30
|
+
*/
|
|
31
|
+
MISSING_CAPTURE_INSTANCE = "missing_capture_instance"
|
|
32
|
+
}
|
|
33
|
+
interface SchemaChangeBase<Type extends SchemaChangeType> {
|
|
34
|
+
type: Type;
|
|
35
|
+
/**
|
|
36
|
+
* The replicated table the change applies to.
|
|
37
|
+
*/
|
|
38
|
+
table: MSSQLSourceTable;
|
|
39
|
+
}
|
|
40
|
+
export interface TableRenameChange extends SchemaChangeBase<SchemaChangeType.TABLE_RENAME> {
|
|
41
|
+
/**
|
|
42
|
+
* The name the table was renamed to. Only used in the error reported for the rename.
|
|
43
|
+
*/
|
|
44
|
+
newTable: SourceTableChangeRef;
|
|
45
|
+
}
|
|
46
|
+
export type TableDropChange = SchemaChangeBase<SchemaChangeType.TABLE_DROP>;
|
|
47
|
+
export interface TableColumnChanges extends SchemaChangeBase<SchemaChangeType.TABLE_COLUMN_CHANGES> {
|
|
48
|
+
/**
|
|
49
|
+
* The pinned capture instance the drift was observed against.
|
|
50
|
+
*/
|
|
51
|
+
captureInstance: CaptureInstance;
|
|
52
|
+
}
|
|
53
|
+
export interface NewCaptureInstanceChange extends SchemaChangeBase<SchemaChangeType.NEW_CAPTURE_INSTANCE> {
|
|
54
|
+
/**
|
|
55
|
+
* The newer instance that is available but will not be adopted by this stream.
|
|
56
|
+
*/
|
|
57
|
+
newCaptureInstance: CaptureInstance;
|
|
58
|
+
}
|
|
59
|
+
export interface MissingCaptureInstanceChange extends SchemaChangeBase<SchemaChangeType.MISSING_CAPTURE_INSTANCE> {
|
|
60
|
+
/**
|
|
61
|
+
* A newer instance that replaced the pinned one, if CDC is still enabled for the table. Only used
|
|
62
|
+
* to report the right recovery step.
|
|
63
|
+
*/
|
|
64
|
+
replacementInstance?: CaptureInstance;
|
|
65
|
+
}
|
|
66
|
+
export type SchemaChange = TableRenameChange | TableDropChange | TableColumnChanges | NewCaptureInstanceChange | MissingCaptureInstanceChange;
|
|
67
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema changes are detected to warn or error on, not applied automatically. Polling cannot be
|
|
3
|
+
* made atomic with a commit, so the replicated schema stays fixed until the next deploy.
|
|
4
|
+
*
|
|
5
|
+
* Drops and renames fail the job because they have no known LSN. Continuing could skip unread
|
|
6
|
+
* changes. Existing replicated data is kept for the next deploy to clean up.
|
|
7
|
+
*/
|
|
8
|
+
export var SchemaChangeType;
|
|
9
|
+
(function (SchemaChangeType) {
|
|
10
|
+
/**
|
|
11
|
+
* A replicated table was renamed.
|
|
12
|
+
*/
|
|
13
|
+
SchemaChangeType["TABLE_RENAME"] = "table_rename";
|
|
14
|
+
/**
|
|
15
|
+
* A replicated table was dropped.
|
|
16
|
+
*/
|
|
17
|
+
SchemaChangeType["TABLE_DROP"] = "table_drop";
|
|
18
|
+
/**
|
|
19
|
+
* The source columns changed. The pinned capture schema remains active.
|
|
20
|
+
*/
|
|
21
|
+
SchemaChangeType["TABLE_COLUMN_CHANGES"] = "table_column_changes";
|
|
22
|
+
/**
|
|
23
|
+
* A newer capture instance exists, but the pinned one is still available.
|
|
24
|
+
*/
|
|
25
|
+
SchemaChangeType["NEW_CAPTURE_INSTANCE"] = "new_capture_instance";
|
|
26
|
+
/**
|
|
27
|
+
* The pinned capture instance is no longer available.
|
|
28
|
+
*/
|
|
29
|
+
SchemaChangeType["MISSING_CAPTURE_INSTANCE"] = "missing_capture_instance";
|
|
30
|
+
})(SchemaChangeType || (SchemaChangeType = {}));
|
|
31
|
+
//# sourceMappingURL=SchemaChange.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaChange.js","sourceRoot":"","sources":["../../src/replication/SchemaChange.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,CAAN,IAAY,gBAqBX;AArBD,WAAY,gBAAgB;IAC1B;;OAEG;IACH,iDAA6B,CAAA;IAC7B;;OAEG;IACH,6CAAyB,CAAA;IACzB;;OAEG;IACH,iEAA6C,CAAA;IAC7C;;OAEG;IACH,iEAA6C,CAAA;IAC7C;;OAEG;IACH,yEAAqD,CAAA;AACvD,CAAC,EArBW,gBAAgB,KAAhB,gBAAgB,QAqB3B"}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -104,9 +104,14 @@ export interface NormalizedMSSQLConnectionConfig {
|
|
|
104
104
|
port: number;
|
|
105
105
|
database: string;
|
|
106
106
|
schema?: string;
|
|
107
|
+
/** PEM-encoded certificate authority used to validate the SQL Server certificate. */
|
|
108
|
+
cacert?: string;
|
|
109
|
+
/** Server name to use when validating the SQL Server certificate. */
|
|
110
|
+
tls_servername?: string;
|
|
107
111
|
authentication?: Authentication;
|
|
108
112
|
lookup?: LookupFunction;
|
|
109
113
|
additionalConfig: AdditionalConfig;
|
|
114
|
+
heartbeat_interval_seconds: number;
|
|
110
115
|
}
|
|
111
116
|
export declare const MSSQLConnectionConfig: t.Intersection<t.Codec<{
|
|
112
117
|
type: string;
|
|
@@ -127,6 +132,10 @@ export declare const MSSQLConnectionConfig: t.Intersection<t.Codec<{
|
|
|
127
132
|
schema: t.OptionalCodec<t.Codec<string, string, string, t.CodecProps>>;
|
|
128
133
|
hostname: t.OptionalCodec<t.Codec<string, string, string, t.CodecProps>>;
|
|
129
134
|
port: t.OptionalCodec<t.Codec<number, string | number, string, t.CodecProps>>;
|
|
135
|
+
/** PEM-encoded certificate authority used to validate the SQL Server certificate. */
|
|
136
|
+
cacert: t.OptionalCodec<t.Codec<string, string, string, t.CodecProps>>;
|
|
137
|
+
/** Server name to use when validating the SQL Server certificate. */
|
|
138
|
+
tls_servername: t.OptionalCodec<t.Codec<string, string, string, t.CodecProps>>;
|
|
130
139
|
authentication: t.OptionalCodec<t.Codec<{
|
|
131
140
|
type: "azure-active-directory-service-principal-secret";
|
|
132
141
|
options: {
|
|
@@ -164,6 +173,10 @@ export declare const MSSQLConnectionConfig: t.Intersection<t.Codec<{
|
|
|
164
173
|
pollingBatchSize?: number | undefined;
|
|
165
174
|
trustServerCertificate?: boolean | undefined;
|
|
166
175
|
}, string, t.CodecProps>>;
|
|
176
|
+
/**
|
|
177
|
+
* Interval in seconds between source connection heartbeats. Null or omitted uses the default.
|
|
178
|
+
*/
|
|
179
|
+
heartbeat_interval_seconds: t.OptionalCodec<t.Codec<number | null, number | null, string, t.CodecProps>>;
|
|
167
180
|
}>>;
|
|
168
181
|
/**
|
|
169
182
|
* Config input specified when starting services
|
package/dist/types/types.js
CHANGED
|
@@ -5,6 +5,9 @@ import * as urijs from 'uri-js';
|
|
|
5
5
|
export const DEFAULT_POLLING_BATCH_SIZE = 10;
|
|
6
6
|
export const DEFAULT_POLLING_INTERVAL_MS = 1000;
|
|
7
7
|
export const MSSQL_CONNECTION_TYPE = 'mssql';
|
|
8
|
+
const DEFAULT_HEARTBEAT_INTERVAL_SECONDS = 60;
|
|
9
|
+
const MIN_HEARTBEAT_INTERVAL_SECONDS = 5;
|
|
10
|
+
const MAX_HEARTBEAT_INTERVAL_SECONDS = 60;
|
|
8
11
|
export const AzureActiveDirectoryServicePrincipalSecret = t.object({
|
|
9
12
|
type: t.literal('azure-active-directory-service-principal-secret'),
|
|
10
13
|
options: t.object({
|
|
@@ -60,9 +63,17 @@ export const MSSQLConnectionConfig = service_types.configFile.DataSourceConfig.a
|
|
|
60
63
|
schema: t.string.optional(),
|
|
61
64
|
hostname: t.string.optional(),
|
|
62
65
|
port: service_types.configFile.portCodec.optional(),
|
|
66
|
+
/** PEM-encoded certificate authority used to validate the SQL Server certificate. */
|
|
67
|
+
cacert: t.string.optional(),
|
|
68
|
+
/** Server name to use when validating the SQL Server certificate. */
|
|
69
|
+
tls_servername: t.string.optional(),
|
|
63
70
|
authentication: Authentication.optional(),
|
|
64
71
|
reject_ip_ranges: t.array(t.string).optional(),
|
|
65
|
-
additionalConfig: AdditionalConfig.optional()
|
|
72
|
+
additionalConfig: AdditionalConfig.optional(),
|
|
73
|
+
/**
|
|
74
|
+
* Interval in seconds between source connection heartbeats. Null or omitted uses the default.
|
|
75
|
+
*/
|
|
76
|
+
heartbeat_interval_seconds: service_types.orNull(t.number).optional()
|
|
66
77
|
}));
|
|
67
78
|
/**
|
|
68
79
|
* Validate and normalize connection options.
|
|
@@ -98,6 +109,9 @@ export function normalizeConnectionConfig(options) {
|
|
|
98
109
|
if (database == '') {
|
|
99
110
|
throw new ServiceError(ErrorCode.PSYNC_S1105, `MSSQL connection: database required`);
|
|
100
111
|
}
|
|
112
|
+
if (options.cacert && options.additionalConfig?.trustServerCertificate) {
|
|
113
|
+
throw new ServiceError(ErrorCode.PSYNC_S1604, 'MSSQL connection: cacert cannot be used with trustServerCertificate because certificate validation would be disabled');
|
|
114
|
+
}
|
|
101
115
|
const lookup = makeHostnameLookupFunction(hostname, { reject_ip_ranges: options.reject_ip_ranges ?? [] });
|
|
102
116
|
return {
|
|
103
117
|
id: options.id ?? 'default',
|
|
@@ -107,15 +121,27 @@ export function normalizeConnectionConfig(options) {
|
|
|
107
121
|
hostname,
|
|
108
122
|
port,
|
|
109
123
|
database,
|
|
124
|
+
cacert: options.cacert,
|
|
125
|
+
tls_servername: options.tls_servername,
|
|
110
126
|
lookup,
|
|
111
127
|
authentication: options.authentication,
|
|
112
128
|
additionalConfig: {
|
|
113
129
|
pollingIntervalMs: options.additionalConfig?.pollingIntervalMs ?? DEFAULT_POLLING_INTERVAL_MS,
|
|
114
130
|
pollingBatchSize: options.additionalConfig?.pollingBatchSize ?? DEFAULT_POLLING_BATCH_SIZE,
|
|
115
131
|
trustServerCertificate: options.additionalConfig?.trustServerCertificate ?? false
|
|
116
|
-
}
|
|
132
|
+
},
|
|
133
|
+
heartbeat_interval_seconds: normalizeHeartbeatInterval(options.heartbeat_interval_seconds)
|
|
117
134
|
};
|
|
118
135
|
}
|
|
136
|
+
function normalizeHeartbeatInterval(value) {
|
|
137
|
+
if (value == null) {
|
|
138
|
+
return DEFAULT_HEARTBEAT_INTERVAL_SECONDS;
|
|
139
|
+
}
|
|
140
|
+
if (!Number.isFinite(value) || value < MIN_HEARTBEAT_INTERVAL_SECONDS || value > MAX_HEARTBEAT_INTERVAL_SECONDS) {
|
|
141
|
+
throw new ServiceError(ErrorCode.PSYNC_S1109, `MSSQL connection: heartbeat_interval_seconds must be between ${MIN_HEARTBEAT_INTERVAL_SECONDS} and ${MAX_HEARTBEAT_INTERVAL_SECONDS} seconds`);
|
|
142
|
+
}
|
|
143
|
+
return value;
|
|
144
|
+
}
|
|
119
145
|
export function baseUri(config) {
|
|
120
146
|
return `mssql://${config.hostname}:${config.port}/${config.database}`;
|
|
121
147
|
}
|
package/dist/types/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,0BAA0B,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACxG,OAAO,KAAK,aAAa,MAAM,0BAA0B,CAAC;AAE1D,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAC9B,OAAO,KAAK,KAAK,MAAM,QAAQ,CAAC;AAEhC,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAC7C,MAAM,CAAC,MAAM,2BAA2B,GAAG,IAAI,CAAC;AAChD,MAAM,CAAC,MAAM,qBAAqB,GAAG,OAAgB,CAAC;AAEtD,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC,CAAC,MAAM,CAAC;IACjE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,iDAAiD,CAAC;IAClE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB;;WAEG;QACH,QAAQ,EAAE,CAAC,CAAC,MAAM;QAClB;;WAEG;QACH,YAAY,EAAE,CAAC,CAAC,MAAM;QACtB;;WAEG;QACH,QAAQ,EAAE,CAAC,CAAC,MAAM;KACnB,CAAC;CACH,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB;;WAEG;QACH,QAAQ,EAAE,CAAC,CAAC,MAAM;QAClB;;WAEG;QACH,QAAQ,EAAE,CAAC,CAAC,MAAM;KACnB,CAAC;CACH,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,cAAc,GAAG,qBAAqB,CAAC,EAAE,CAAC,0CAA0C,CAAC,CAAC;AAGnG,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC;;OAEG;IACH,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE;IACtC;;OAEG;IACH,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE;IAErC;;;OAGG;IACH,sBAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;CAC7C,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/mssql.js
CHANGED
|
@@ -264,7 +264,7 @@ export async function getDebugTableInfo(options) {
|
|
|
264
264
|
if (captureInstanceDetails && captureInstanceDetails.instances[0].pendingSchemaChanges.length > 0) {
|
|
265
265
|
schemaDriftError = {
|
|
266
266
|
level: 'warning',
|
|
267
|
-
message: `Source table ${toQualifiedTableName(schema, table.name)} has schema changes not reflected in the CDC capture instance.
|
|
267
|
+
message: `Source table ${toQualifiedTableName(schema, table.name)} has schema changes not reflected in the CDC capture instance. Create a replacement CDC capture instance with the intended columns, update the sync config if needed, and deploy a new sync config. If the change requires disabling CDC, re-enable CDC before deploying.
|
|
268
268
|
Pending schema changes: ${captureInstanceDetails.instances[0].pendingSchemaChanges.join(', \n')}`
|
|
269
269
|
};
|
|
270
270
|
}
|
package/dist/utils/schema.d.ts
CHANGED
|
@@ -17,11 +17,24 @@ export interface ReplicationIdentityColumnsResult {
|
|
|
17
17
|
}
|
|
18
18
|
export declare function getReplicationIdentityColumns(options: GetReplicationIdentityColumnsOptions): Promise<ReplicationIdentityColumnsResult>;
|
|
19
19
|
export interface SourceTableChangeRef {
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* `sys.tables.object_id`, which SQL Server always reports as an int. Narrower than
|
|
22
|
+
* `SourceEntityDescriptor.objectId`, which has to accommodate other source databases.
|
|
23
|
+
*/
|
|
24
|
+
objectId: number;
|
|
21
25
|
schema: string;
|
|
22
26
|
name: string;
|
|
23
27
|
}
|
|
24
28
|
export type ResolvedTable = SourceTableChangeRef;
|
|
29
|
+
export declare const SCHEMA_WILDCARD_MESSAGE = "Schema wildcards (\"%\") in table patterns are not supported for SQL Server connections.";
|
|
30
|
+
/**
|
|
31
|
+
* Wildcards would allow the replicated table set to change between polls, so they are rejected.
|
|
32
|
+
*/
|
|
33
|
+
export declare function tableWildcardMessage(tablePattern: TablePattern): string;
|
|
34
|
+
/**
|
|
35
|
+
* Returns the reason this pattern cannot be replicated, or null if it is supported.
|
|
36
|
+
*/
|
|
37
|
+
export declare function unsupportedTablePatternMessage(tablePattern: TablePattern): string | null;
|
|
25
38
|
export declare function getTablesFromPattern(connectionManager: MSSQLConnectionManager, tablePattern: TablePattern): Promise<ResolvedTable[]>;
|
|
26
39
|
export interface GetPendingSchemaChangesOptions {
|
|
27
40
|
connectionManager: MSSQLConnectionManager;
|
package/dist/utils/schema.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { logger } from '@powersync/lib-services-framework';
|
|
1
|
+
import { ErrorCode, logger, ServiceError } from '@powersync/lib-services-framework';
|
|
2
2
|
import sql from 'mssql';
|
|
3
3
|
async function getColumns(options) {
|
|
4
4
|
const { connectionManager, schema, tableName } = options;
|
|
@@ -97,53 +97,51 @@ export async function getReplicationIdentityColumns(options) {
|
|
|
97
97
|
identity: 'full'
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
|
-
export
|
|
100
|
+
export const SCHEMA_WILDCARD_MESSAGE = 'Schema wildcards ("%") in table patterns are not supported for SQL Server connections.';
|
|
101
|
+
/**
|
|
102
|
+
* Wildcards would allow the replicated table set to change between polls, so they are rejected.
|
|
103
|
+
*/
|
|
104
|
+
export function tableWildcardMessage(tablePattern) {
|
|
105
|
+
return (`Table wildcards ("%") are not supported for SQL Server connections: "${tablePattern.tablePattern}". ` +
|
|
106
|
+
`List each table explicitly.`);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Returns the reason this pattern cannot be replicated, or null if it is supported.
|
|
110
|
+
*/
|
|
111
|
+
export function unsupportedTablePatternMessage(tablePattern) {
|
|
112
|
+
if (tablePattern.isSchemaWildcard) {
|
|
113
|
+
return SCHEMA_WILDCARD_MESSAGE;
|
|
114
|
+
}
|
|
101
115
|
if (tablePattern.isWildcard) {
|
|
102
|
-
|
|
103
|
-
SELECT
|
|
104
|
-
tbl.name AS [table],
|
|
105
|
-
sch.name AS [schema],
|
|
106
|
-
tbl.object_id AS object_id
|
|
107
|
-
FROM sys.tables tbl
|
|
108
|
-
JOIN sys.schemas sch ON tbl.schema_id = sch.schema_id
|
|
109
|
-
WHERE sch.name = @schema
|
|
110
|
-
AND tbl.name LIKE @tablePattern
|
|
111
|
-
`, [
|
|
112
|
-
{ name: 'schema', type: sql.VarChar(sql.MAX), value: tablePattern.schema },
|
|
113
|
-
{ name: 'tablePattern', type: sql.VarChar(sql.MAX), value: tablePattern.tablePattern }
|
|
114
|
-
]);
|
|
115
|
-
return tableResults
|
|
116
|
-
.map((row) => {
|
|
117
|
-
return {
|
|
118
|
-
objectId: row.object_id,
|
|
119
|
-
schema: row.schema,
|
|
120
|
-
name: row.table
|
|
121
|
-
};
|
|
122
|
-
})
|
|
123
|
-
.filter((table) => table.name.startsWith(tablePattern.tablePrefix));
|
|
116
|
+
return tableWildcardMessage(tablePattern);
|
|
124
117
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
FROM sys.tables tbl
|
|
132
|
-
JOIN sys.schemas sch ON tbl.schema_id = sch.schema_id
|
|
133
|
-
WHERE sch.name = @schema
|
|
134
|
-
AND tbl.name = @tablePattern
|
|
135
|
-
`, [
|
|
136
|
-
{ name: 'schema', type: sql.VarChar(sql.MAX), value: tablePattern.schema },
|
|
137
|
-
{ name: 'tablePattern', type: sql.VarChar(sql.MAX), value: tablePattern.tablePattern }
|
|
138
|
-
]);
|
|
139
|
-
return tableResults.map((row) => {
|
|
140
|
-
return {
|
|
141
|
-
objectId: row.object_id,
|
|
142
|
-
schema: row.schema,
|
|
143
|
-
name: row.table
|
|
144
|
-
};
|
|
145
|
-
});
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
export async function getTablesFromPattern(connectionManager, tablePattern) {
|
|
121
|
+
const unsupported = unsupportedTablePatternMessage(tablePattern);
|
|
122
|
+
if (unsupported != null) {
|
|
123
|
+
throw new ServiceError(ErrorCode.PSYNC_R2201, unsupported);
|
|
146
124
|
}
|
|
125
|
+
const { recordset: tableResults } = await connectionManager.query(`
|
|
126
|
+
SELECT
|
|
127
|
+
tbl.name AS [table],
|
|
128
|
+
sch.name AS [schema],
|
|
129
|
+
tbl.object_id AS object_id
|
|
130
|
+
FROM sys.tables tbl
|
|
131
|
+
JOIN sys.schemas sch ON tbl.schema_id = sch.schema_id
|
|
132
|
+
WHERE sch.name = @schema
|
|
133
|
+
AND tbl.name = @tablePattern
|
|
134
|
+
`, [
|
|
135
|
+
{ name: 'schema', type: sql.VarChar(sql.MAX), value: tablePattern.schema },
|
|
136
|
+
{ name: 'tablePattern', type: sql.VarChar(sql.MAX), value: tablePattern.tablePattern }
|
|
137
|
+
]);
|
|
138
|
+
return tableResults.map((row) => {
|
|
139
|
+
return {
|
|
140
|
+
objectId: row.object_id,
|
|
141
|
+
schema: row.schema,
|
|
142
|
+
name: row.table
|
|
143
|
+
};
|
|
144
|
+
});
|
|
147
145
|
}
|
|
148
146
|
/**
|
|
149
147
|
* Returns the DDL commands that have been applied to the source table since the capture instance was created.
|