@powersync/service-module-mysql 0.0.0-dev-20260225160713 → 0.0.0-dev-20260511080634
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 +104 -5
- package/dist/api/MySQLRouteAPIAdapter.js +1 -1
- package/dist/api/MySQLRouteAPIAdapter.js.map +1 -1
- package/dist/common/check-source-configuration.js +12 -1
- package/dist/common/check-source-configuration.js.map +1 -1
- package/dist/common/common-index.d.ts +1 -1
- package/dist/common/common-index.js +1 -1
- package/dist/common/common-index.js.map +1 -1
- package/dist/common/mysql-to-sqlite.d.ts +2 -2
- package/dist/common/mysql-to-sqlite.js +1 -1
- package/dist/common/mysql-to-sqlite.js.map +1 -1
- package/dist/common/schema-utils.d.ts +1 -1
- package/dist/common/schema-utils.js.map +1 -1
- package/dist/module/MySQLModule.js +3 -3
- package/dist/module/MySQLModule.js.map +1 -1
- package/dist/replication/BinLogReplicationJob.d.ts +1 -1
- package/dist/replication/BinLogReplicationJob.js +3 -3
- package/dist/replication/BinLogReplicationJob.js.map +1 -1
- package/dist/replication/BinLogReplicator.d.ts +0 -1
- package/dist/replication/BinLogReplicator.js +1 -23
- package/dist/replication/BinLogReplicator.js.map +1 -1
- package/dist/replication/BinLogStream.d.ts +3 -11
- package/dist/replication/BinLogStream.js +30 -45
- package/dist/replication/BinLogStream.js.map +1 -1
- package/dist/replication/MySQLConnectionManager.d.ts +3 -3
- package/dist/replication/MySQLConnectionManager.js +1 -1
- package/dist/replication/MySQLConnectionManager.js.map +1 -1
- package/dist/replication/MySQLConnectionManagerFactory.d.ts +1 -1
- package/dist/replication/MySQLConnectionManagerFactory.js.map +1 -1
- package/dist/replication/zongji/BinLogListener.d.ts +4 -4
- package/dist/replication/zongji/BinLogListener.js +7 -7
- package/dist/replication/zongji/BinLogListener.js.map +1 -1
- package/dist/replication/zongji/zongji-utils.d.ts +1 -1
- package/dist/utils/mysql-utils.d.ts +2 -2
- package/dist/utils/mysql-utils.js +1 -1
- package/dist/utils/mysql-utils.js.map +1 -1
- package/dist/utils/parser-utils.d.ts +1 -1
- package/package.json +10 -10
- package/src/api/MySQLRouteAPIAdapter.ts +2 -2
- package/src/common/check-source-configuration.ts +16 -1
- package/src/common/common-index.ts +1 -1
- package/src/common/mysql-to-sqlite.ts +3 -3
- package/src/common/schema-utils.ts +2 -2
- package/src/module/MySQLModule.ts +3 -3
- package/src/replication/BinLogReplicationJob.ts +3 -3
- package/src/replication/BinLogReplicator.ts +1 -26
- package/src/replication/BinLogStream.ts +35 -44
- package/src/replication/MySQLConnectionManager.ts +4 -4
- package/src/replication/MySQLConnectionManagerFactory.ts +1 -1
- package/src/replication/zongji/BinLogListener.ts +10 -10
- package/src/replication/zongji/zongji-utils.ts +6 -6
- package/src/utils/mysql-utils.ts +3 -3
- package/src/utils/parser-utils.ts +1 -1
- package/test/src/BinLogListener.test.ts +37 -26
- package/test/src/BinLogStream.test.ts +4 -2
- package/test/src/BinlogStreamUtils.ts +20 -7
- package/test/src/config.test.ts +1 -1
- package/test/src/env.ts +1 -1
- package/test/src/mysql-to-sqlite.test.ts +5 -6
- package/test/src/mysql-utils.test.ts +1 -1
- package/test/src/parser-utils.test.ts +1 -1
- package/test/src/schema-changes.test.ts +6 -5
- package/test/src/util.ts +9 -9
- package/test/tsconfig.json +0 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { qualifiedMySQLTable } from '@module/utils/mysql-utils.js';
|
|
1
2
|
import { storage } from '@powersync/service-core';
|
|
2
3
|
import { METRICS_HELPER, putOp, removeOp } from '@powersync/service-core-tests';
|
|
3
4
|
import { ReplicationMetric } from '@powersync/service-types';
|
|
@@ -5,7 +6,6 @@ import { v4 as uuid } from 'uuid';
|
|
|
5
6
|
import { describe, expect, test } from 'vitest';
|
|
6
7
|
import { BinlogStreamTestContext } from './BinlogStreamUtils.js';
|
|
7
8
|
import { createTestDb, describeWithStorage } from './util.js';
|
|
8
|
-
import { qualifiedMySQLTable } from '@module/utils/mysql-utils.js';
|
|
9
9
|
|
|
10
10
|
const BASIC_SYNC_RULES = `
|
|
11
11
|
bucket_definitions:
|
|
@@ -18,7 +18,9 @@ describe('BinLogStream tests', () => {
|
|
|
18
18
|
describeWithStorage({ timeout: 20_000 }, defineBinlogStreamTests);
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
function defineBinlogStreamTests(
|
|
21
|
+
function defineBinlogStreamTests(config: storage.TestStorageConfig) {
|
|
22
|
+
const factory = config.factory;
|
|
23
|
+
|
|
22
24
|
test('Replicate basic values', async () => {
|
|
23
25
|
await using context = await BinlogStreamTestContext.open(factory);
|
|
24
26
|
const { connectionManager } = context;
|
|
@@ -15,10 +15,10 @@ import {
|
|
|
15
15
|
SyncRulesBucketStorage,
|
|
16
16
|
updateSyncRulesFromYaml
|
|
17
17
|
} from '@powersync/service-core';
|
|
18
|
-
import { METRICS_HELPER, test_utils } from '@powersync/service-core-tests';
|
|
18
|
+
import { bucketRequest, METRICS_HELPER, test_utils } from '@powersync/service-core-tests';
|
|
19
19
|
import mysqlPromise from 'mysql2/promise';
|
|
20
|
-
import { clearTestDb, TEST_CONNECTION_OPTIONS } from './util.js';
|
|
21
20
|
import timers from 'timers/promises';
|
|
21
|
+
import { clearTestDb, TEST_CONNECTION_OPTIONS } from './util.js';
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Tests operating on the binlog stream need to configure the stream and manage asynchronous
|
|
@@ -33,6 +33,7 @@ export class BinlogStreamTestContext {
|
|
|
33
33
|
private streamPromise?: Promise<void>;
|
|
34
34
|
public storage?: SyncRulesBucketStorage;
|
|
35
35
|
private replicationDone = false;
|
|
36
|
+
private syncRulesContent?: storage.PersistedSyncRulesContent;
|
|
36
37
|
|
|
37
38
|
static async open(factory: storage.TestStorageFactory, options?: { doNotClear?: boolean }) {
|
|
38
39
|
const f = await factory({ doNotClear: options?.doNotClear });
|
|
@@ -73,6 +74,7 @@ export class BinlogStreamTestContext {
|
|
|
73
74
|
const syncRules = await this.factory.updateSyncRules(
|
|
74
75
|
updateSyncRulesFromYaml(content, { validate: true, storageVersion: LEGACY_STORAGE_VERSION })
|
|
75
76
|
);
|
|
77
|
+
this.syncRulesContent = syncRules;
|
|
76
78
|
this.storage = this.factory.getInstance(syncRules);
|
|
77
79
|
return this.storage!;
|
|
78
80
|
}
|
|
@@ -80,9 +82,10 @@ export class BinlogStreamTestContext {
|
|
|
80
82
|
async loadNextSyncRules() {
|
|
81
83
|
const syncRules = await this.factory.getNextSyncRulesContent();
|
|
82
84
|
if (syncRules == null) {
|
|
83
|
-
throw new Error(`Next
|
|
85
|
+
throw new Error(`Next replication stream not available`);
|
|
84
86
|
}
|
|
85
87
|
|
|
88
|
+
this.syncRulesContent = syncRules;
|
|
86
89
|
this.storage = this.factory.getInstance(syncRules);
|
|
87
90
|
return this.storage!;
|
|
88
91
|
}
|
|
@@ -90,14 +93,22 @@ export class BinlogStreamTestContext {
|
|
|
90
93
|
async loadActiveSyncRules() {
|
|
91
94
|
const syncRules = await this.factory.getActiveSyncRulesContent();
|
|
92
95
|
if (syncRules == null) {
|
|
93
|
-
throw new Error(`Active
|
|
96
|
+
throw new Error(`Active replication stream not available`);
|
|
94
97
|
}
|
|
95
98
|
|
|
99
|
+
this.syncRulesContent = syncRules;
|
|
96
100
|
this.storage = this.factory.getInstance(syncRules);
|
|
97
101
|
this.replicationDone = true;
|
|
98
102
|
return this.storage!;
|
|
99
103
|
}
|
|
100
104
|
|
|
105
|
+
private getSyncRulesContent(): storage.PersistedSyncRulesContent {
|
|
106
|
+
if (this.syncRulesContent == null) {
|
|
107
|
+
throw new Error('Sync config not configured - call updateSyncRules() first');
|
|
108
|
+
}
|
|
109
|
+
return this.syncRulesContent;
|
|
110
|
+
}
|
|
111
|
+
|
|
101
112
|
get binlogStream(): BinLogStream {
|
|
102
113
|
if (this.storage == null) {
|
|
103
114
|
throw new Error('updateSyncRules() first');
|
|
@@ -154,7 +165,8 @@ export class BinlogStreamTestContext {
|
|
|
154
165
|
|
|
155
166
|
async getBucketsDataBatch(buckets: Record<string, InternalOpId>, options?: { timeout?: number }) {
|
|
156
167
|
const checkpoint = await this.getCheckpoint(options);
|
|
157
|
-
const
|
|
168
|
+
const syncRules = this.getSyncRulesContent();
|
|
169
|
+
const map = Object.entries(buckets).map(([bucket, start]) => bucketRequest(syncRules, bucket, start));
|
|
158
170
|
return test_utils.fromAsync(this.storage!.getBucketDataBatch(checkpoint, map));
|
|
159
171
|
}
|
|
160
172
|
|
|
@@ -167,8 +179,9 @@ export class BinlogStreamTestContext {
|
|
|
167
179
|
if (typeof start == 'string') {
|
|
168
180
|
start = BigInt(start);
|
|
169
181
|
}
|
|
182
|
+
const syncRules = this.getSyncRulesContent();
|
|
170
183
|
const checkpoint = await this.getCheckpoint(options);
|
|
171
|
-
const map =
|
|
184
|
+
const map = [bucketRequest(syncRules, bucket, start)];
|
|
172
185
|
const batch = this.storage!.getBucketDataBatch(checkpoint, map);
|
|
173
186
|
const batches = await test_utils.fromAsync(batch);
|
|
174
187
|
return batches[0]?.chunkData.data ?? [];
|
|
@@ -193,7 +206,7 @@ export async function getClientCheckpoint(
|
|
|
193
206
|
const storage = await storageFactory.getActiveStorage();
|
|
194
207
|
const cp = await storage?.getCheckpoint();
|
|
195
208
|
if (cp == null) {
|
|
196
|
-
throw new Error('No
|
|
209
|
+
throw new Error('No replication stream available');
|
|
197
210
|
}
|
|
198
211
|
lastCp = cp;
|
|
199
212
|
if (cp.lsn && cp.lsn >= gtid.comparable) {
|
package/test/src/config.test.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { describe, expect, test } from 'vitest';
|
|
2
1
|
import {
|
|
3
2
|
normalizeConnectionConfig,
|
|
4
3
|
parseMySQLConnectionParam,
|
|
5
4
|
parseMySQLConnectionParams
|
|
6
5
|
} from '@module/types/types.js';
|
|
6
|
+
import { describe, expect, test } from 'vitest';
|
|
7
7
|
|
|
8
8
|
describe('config', () => {
|
|
9
9
|
test('Should resolve database', () => {
|
package/test/src/env.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { utils } from '@powersync/lib-services-framework';
|
|
|
3
3
|
export const env = utils.collectEnvironmentVariables({
|
|
4
4
|
MYSQL_TEST_URI: utils.type.string.default('mysql://root:mypassword@localhost:3306/mydatabase'),
|
|
5
5
|
MONGO_TEST_URL: utils.type.string.default('mongodb://localhost:27017/powersync_test'),
|
|
6
|
-
PG_STORAGE_TEST_URL: utils.type.string.default('postgres://postgres:postgres@localhost:
|
|
6
|
+
PG_STORAGE_TEST_URL: utils.type.string.default('postgres://postgres:postgres@localhost:5432/powersync_storage_test'),
|
|
7
7
|
CI: utils.type.boolean.default('false'),
|
|
8
8
|
SLOW_TESTS: utils.type.boolean.default('false'),
|
|
9
9
|
TEST_MONGO_STORAGE: utils.type.boolean.default('true'),
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
+
import * as common from '@module/common/common-index.js';
|
|
2
|
+
import { toColumnDescriptors } from '@module/common/common-index.js';
|
|
3
|
+
import { MySQLConnectionManager } from '@module/replication/MySQLConnectionManager.js';
|
|
4
|
+
import { eventIsWriteMutation, eventIsXid } from '@module/replication/zongji/zongji-utils.js';
|
|
5
|
+
import { BinLogEvent, ZongJi } from '@powersync/mysql-zongji';
|
|
1
6
|
import {
|
|
2
7
|
applyRowContext,
|
|
3
8
|
CompatibilityContext,
|
|
4
9
|
SqliteInputRow,
|
|
5
|
-
SqliteRow,
|
|
6
10
|
TimeValuePrecision
|
|
7
11
|
} from '@powersync/service-sync-rules';
|
|
8
12
|
import { afterAll, describe, expect, test } from 'vitest';
|
|
9
13
|
import { clearTestDb, TEST_CONNECTION_OPTIONS } from './util.js';
|
|
10
|
-
import { eventIsWriteMutation, eventIsXid } from '@module/replication/zongji/zongji-utils.js';
|
|
11
|
-
import * as common from '@module/common/common-index.js';
|
|
12
|
-
import { BinLogEvent, ZongJi } from '@powersync/mysql-zongji';
|
|
13
|
-
import { MySQLConnectionManager } from '@module/replication/MySQLConnectionManager.js';
|
|
14
|
-
import { toColumnDescriptors } from '@module/common/common-index.js';
|
|
15
14
|
|
|
16
15
|
describe('MySQL Data Types', () => {
|
|
17
16
|
const connectionManager = new MySQLConnectionManager(TEST_CONNECTION_OPTIONS, {});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { describe, expect, test } from 'vitest';
|
|
2
1
|
import { matchedSchemaChangeQuery } from '@module/utils/parser-utils.js';
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
3
3
|
|
|
4
4
|
describe('MySQL Parser Util Tests', () => {
|
|
5
5
|
test('matchedSchemaChangeQuery function', () => {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { compareIds, putOp, removeOp, test_utils } from '@powersync/service-core-tests';
|
|
2
2
|
import { beforeAll, describe, expect, test } from 'vitest';
|
|
3
3
|
|
|
4
|
-
import { storage } from '@powersync/service-core';
|
|
5
|
-
import { createTestDb, describeWithStorage, TEST_CONNECTION_OPTIONS } from './util.js';
|
|
6
|
-
import { BinlogStreamTestContext } from './BinlogStreamUtils.js';
|
|
7
|
-
import timers from 'timers/promises';
|
|
8
4
|
import { MySQLConnectionManager } from '@module/replication/MySQLConnectionManager.js';
|
|
9
5
|
import { getMySQLVersion, qualifiedMySQLTable, satisfiesVersion } from '@module/utils/mysql-utils.js';
|
|
6
|
+
import { storage } from '@powersync/service-core';
|
|
7
|
+
import timers from 'timers/promises';
|
|
8
|
+
import { BinlogStreamTestContext } from './BinlogStreamUtils.js';
|
|
9
|
+
import { createTestDb, describeWithStorage, TEST_CONNECTION_OPTIONS } from './util.js';
|
|
10
10
|
|
|
11
11
|
describe('MySQL Schema Changes', () => {
|
|
12
12
|
describeWithStorage({ timeout: 20_000 }, defineTests);
|
|
@@ -26,7 +26,8 @@ const PUT_T3 = test_utils.putOp('test_data', { id: 't3', description: 'test3' })
|
|
|
26
26
|
const REMOVE_T1 = test_utils.removeOp('test_data', 't1');
|
|
27
27
|
const REMOVE_T2 = test_utils.removeOp('test_data', 't2');
|
|
28
28
|
|
|
29
|
-
function defineTests(
|
|
29
|
+
function defineTests(config: storage.TestStorageConfig) {
|
|
30
|
+
const factory = config.factory;
|
|
30
31
|
let isMySQL57: boolean = false;
|
|
31
32
|
|
|
32
33
|
beforeAll(async () => {
|
package/test/src/util.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
+
import * as common from '@module/common/common-index.js';
|
|
2
|
+
import { MySQLConnectionManager } from '@module/replication/MySQLConnectionManager.js';
|
|
3
|
+
import { BinLogEventHandler, BinLogListener, Row, SchemaChange } from '@module/replication/zongji/BinLogListener.js';
|
|
1
4
|
import * as types from '@module/types/types.js';
|
|
2
5
|
import { createRandomServerId, getMySQLVersion, isVersionAtLeast } from '@module/utils/mysql-utils.js';
|
|
6
|
+
import { TableMapEntry } from '@powersync/mysql-zongji';
|
|
7
|
+
import { TestStorageConfig } from '@powersync/service-core';
|
|
3
8
|
import * as mongo_storage from '@powersync/service-module-mongodb-storage';
|
|
4
9
|
import * as postgres_storage from '@powersync/service-module-postgres-storage';
|
|
10
|
+
import { TablePattern } from '@powersync/service-sync-rules';
|
|
5
11
|
import mysqlPromise from 'mysql2/promise';
|
|
6
|
-
import { env } from './env.js';
|
|
7
12
|
import { describe, TestOptions } from 'vitest';
|
|
8
|
-
import {
|
|
9
|
-
import { MySQLConnectionManager } from '@module/replication/MySQLConnectionManager.js';
|
|
10
|
-
import { BinLogEventHandler, BinLogListener, Row, SchemaChange } from '@module/replication/zongji/BinLogListener.js';
|
|
11
|
-
import { TableMapEntry } from '@powersync/mysql-zongji';
|
|
12
|
-
import * as common from '@module/common/common-index.js';
|
|
13
|
-
import { TablePattern } from '@powersync/service-sync-rules';
|
|
13
|
+
import { env } from './env.js';
|
|
14
14
|
|
|
15
15
|
export const TEST_URI = env.MYSQL_TEST_URI;
|
|
16
16
|
|
|
@@ -24,11 +24,11 @@ export const INITIALIZED_MONGO_STORAGE_FACTORY = mongo_storage.test_utils.mongoT
|
|
|
24
24
|
isCI: env.CI
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
export const INITIALIZED_POSTGRES_STORAGE_FACTORY = postgres_storage.test_utils.
|
|
27
|
+
export const INITIALIZED_POSTGRES_STORAGE_FACTORY = postgres_storage.test_utils.postgresTestSetup({
|
|
28
28
|
url: env.PG_STORAGE_TEST_URL
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
export function describeWithStorage(options: TestOptions, fn: (factory:
|
|
31
|
+
export function describeWithStorage(options: TestOptions, fn: (factory: TestStorageConfig) => void) {
|
|
32
32
|
describe.skipIf(!env.TEST_MONGO_STORAGE)(`mongodb storage`, options, function () {
|
|
33
33
|
fn(INITIALIZED_MONGO_STORAGE_FACTORY);
|
|
34
34
|
});
|