@powersync/service-module-mysql 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/LICENSE +3 -3
- package/dist/api/MySQLRouteAPIAdapter.js +1 -1
- package/dist/api/MySQLRouteAPIAdapter.js.map +1 -1
- package/dist/common/mysql-to-sqlite.d.ts +1 -1
- package/dist/common/mysql-to-sqlite.js.map +1 -1
- package/dist/replication/BinLogReplicationJob.js +4 -1
- package/dist/replication/BinLogReplicationJob.js.map +1 -1
- package/dist/replication/BinLogStream.js +18 -3
- package/dist/replication/BinLogStream.js.map +1 -1
- package/dist/replication/zongji/BinLogListener.d.ts +10 -3
- package/dist/replication/zongji/BinLogListener.js +66 -25
- package/dist/replication/zongji/BinLogListener.js.map +1 -1
- package/dist/replication/zongji/zongji-utils.d.ts +3 -1
- package/dist/replication/zongji/zongji-utils.js +6 -0
- package/dist/replication/zongji/zongji-utils.js.map +1 -1
- package/package.json +11 -11
- package/src/api/MySQLRouteAPIAdapter.ts +4 -1
- package/src/common/mysql-to-sqlite.ts +4 -1
- package/src/replication/BinLogReplicationJob.ts +4 -1
- package/src/replication/BinLogStream.ts +20 -3
- package/src/replication/zongji/BinLogListener.ts +72 -28
- package/src/replication/zongji/zongji-utils.ts +11 -1
- package/test/src/BinLogListener.test.ts +57 -96
- package/test/src/mysql-to-sqlite.test.ts +5 -5
- package/test/src/schema-changes.test.ts +1 -5
- package/test/src/util.ts +81 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
import { afterAll, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
BinLogEventHandler,
|
|
4
|
-
BinLogListener,
|
|
5
|
-
Row,
|
|
6
|
-
SchemaChange,
|
|
7
|
-
SchemaChangeType
|
|
8
|
-
} from '@module/replication/zongji/BinLogListener.js';
|
|
2
|
+
import { BinLogListener, SchemaChange, SchemaChangeType } from '@module/replication/zongji/BinLogListener.js';
|
|
9
3
|
import { MySQLConnectionManager } from '@module/replication/MySQLConnectionManager.js';
|
|
10
|
-
import { clearTestDb, createTestDb, TEST_CONNECTION_OPTIONS } from './util.js';
|
|
11
|
-
import { v4 as uuid } from 'uuid';
|
|
12
|
-
import * as common from '@module/common/common-index.js';
|
|
13
4
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
clearTestDb,
|
|
6
|
+
createBinlogListener,
|
|
7
|
+
createTestDb,
|
|
8
|
+
TEST_CONNECTION_OPTIONS,
|
|
9
|
+
TestBinLogEventHandler
|
|
10
|
+
} from './util.js';
|
|
11
|
+
import { v4 as uuid } from 'uuid';
|
|
12
|
+
import { getMySQLVersion, qualifiedMySQLTable, satisfiesVersion } from '@module/utils/mysql-utils.js';
|
|
20
13
|
import crypto from 'crypto';
|
|
21
14
|
import { TablePattern } from '@powersync/service-sync-rules';
|
|
22
15
|
|
|
@@ -46,7 +39,11 @@ describe('BinlogListener tests', () => {
|
|
|
46
39
|
await connectionManager.query(`CREATE TABLE test_DATA (id CHAR(36) PRIMARY KEY, description MEDIUMTEXT)`);
|
|
47
40
|
connection.release();
|
|
48
41
|
eventHandler = new TestBinLogEventHandler();
|
|
49
|
-
binLogListener = await createBinlogListener(
|
|
42
|
+
binLogListener = await createBinlogListener({
|
|
43
|
+
connectionManager,
|
|
44
|
+
sourceTables: [new TablePattern(connectionManager.databaseName, 'test_DATA')],
|
|
45
|
+
eventHandler
|
|
46
|
+
});
|
|
50
47
|
});
|
|
51
48
|
|
|
52
49
|
afterAll(async () => {
|
|
@@ -106,6 +103,14 @@ describe('BinlogListener tests', () => {
|
|
|
106
103
|
await binLogListener.stop();
|
|
107
104
|
});
|
|
108
105
|
|
|
106
|
+
test('Keepalive event', async () => {
|
|
107
|
+
binLogListener.options.keepAliveInactivitySeconds = 1;
|
|
108
|
+
await binLogListener.start();
|
|
109
|
+
await vi.waitFor(() => expect(eventHandler.lastKeepAlive).toBeDefined(), { timeout: 10000 });
|
|
110
|
+
await binLogListener.stop();
|
|
111
|
+
expect(eventHandler.lastKeepAlive).toEqual(binLogListener.options.startGTID.comparable);
|
|
112
|
+
});
|
|
113
|
+
|
|
109
114
|
test('Schema change event: Rename table', async () => {
|
|
110
115
|
await binLogListener.start();
|
|
111
116
|
await connectionManager.query(`ALTER TABLE test_DATA RENAME test_DATA_new`);
|
|
@@ -276,7 +281,11 @@ describe('BinlogListener tests', () => {
|
|
|
276
281
|
test('Schema change event: Drop and Add primary key', async () => {
|
|
277
282
|
await connectionManager.query(`CREATE TABLE test_constraints (id CHAR(36), description VARCHAR(100))`);
|
|
278
283
|
const sourceTables = [new TablePattern(connectionManager.databaseName, 'test_constraints')];
|
|
279
|
-
binLogListener = await createBinlogListener(
|
|
284
|
+
binLogListener = await createBinlogListener({
|
|
285
|
+
connectionManager,
|
|
286
|
+
eventHandler,
|
|
287
|
+
sourceTables
|
|
288
|
+
});
|
|
280
289
|
await binLogListener.start();
|
|
281
290
|
await connectionManager.query(`ALTER TABLE test_constraints ADD PRIMARY KEY (id)`);
|
|
282
291
|
await connectionManager.query(`ALTER TABLE test_constraints DROP PRIMARY KEY`);
|
|
@@ -301,7 +310,11 @@ describe('BinlogListener tests', () => {
|
|
|
301
310
|
test('Schema change event: Add and drop unique constraint', async () => {
|
|
302
311
|
await connectionManager.query(`CREATE TABLE test_constraints (id CHAR(36), description VARCHAR(100))`);
|
|
303
312
|
const sourceTables = [new TablePattern(connectionManager.databaseName, 'test_constraints')];
|
|
304
|
-
binLogListener = await createBinlogListener(
|
|
313
|
+
binLogListener = await createBinlogListener({
|
|
314
|
+
connectionManager,
|
|
315
|
+
eventHandler,
|
|
316
|
+
sourceTables
|
|
317
|
+
});
|
|
305
318
|
await binLogListener.start();
|
|
306
319
|
await connectionManager.query(`ALTER TABLE test_constraints ADD UNIQUE (description)`);
|
|
307
320
|
await connectionManager.query(`ALTER TABLE test_constraints DROP INDEX description`);
|
|
@@ -326,7 +339,11 @@ describe('BinlogListener tests', () => {
|
|
|
326
339
|
test('Schema change event: Add and drop a unique index', async () => {
|
|
327
340
|
await connectionManager.query(`CREATE TABLE test_constraints (id CHAR(36), description VARCHAR(100))`);
|
|
328
341
|
const sourceTables = [new TablePattern(connectionManager.databaseName, 'test_constraints')];
|
|
329
|
-
binLogListener = await createBinlogListener(
|
|
342
|
+
binLogListener = await createBinlogListener({
|
|
343
|
+
connectionManager,
|
|
344
|
+
eventHandler,
|
|
345
|
+
sourceTables
|
|
346
|
+
});
|
|
330
347
|
await binLogListener.start();
|
|
331
348
|
await connectionManager.query(`CREATE UNIQUE INDEX description_idx ON test_constraints (description)`);
|
|
332
349
|
await connectionManager.query(`DROP INDEX description_idx ON test_constraints`);
|
|
@@ -367,7 +384,11 @@ describe('BinlogListener tests', () => {
|
|
|
367
384
|
// If there are multiple schema changes in the binlog processing queue, we only restart the binlog listener once
|
|
368
385
|
// all the schema changes have been processed
|
|
369
386
|
const sourceTables = [new TablePattern(connectionManager.databaseName, 'test_multiple')];
|
|
370
|
-
binLogListener = await createBinlogListener(
|
|
387
|
+
binLogListener = await createBinlogListener({
|
|
388
|
+
connectionManager,
|
|
389
|
+
eventHandler,
|
|
390
|
+
sourceTables
|
|
391
|
+
});
|
|
371
392
|
|
|
372
393
|
await connectionManager.query(`CREATE TABLE test_multiple (id CHAR(36), description VARCHAR(100))`);
|
|
373
394
|
await connectionManager.query(`ALTER TABLE test_multiple ADD COLUMN new_column VARCHAR(10)`);
|
|
@@ -388,7 +409,11 @@ describe('BinlogListener tests', () => {
|
|
|
388
409
|
test('Unprocessed binlog event received that does match the current table schema', async () => {
|
|
389
410
|
// If we process a binlog event for a table which has since had its schema changed, we expect the binlog listener to stop with an error
|
|
390
411
|
const sourceTables = [new TablePattern(connectionManager.databaseName, 'test_failure')];
|
|
391
|
-
binLogListener = await createBinlogListener(
|
|
412
|
+
binLogListener = await createBinlogListener({
|
|
413
|
+
connectionManager,
|
|
414
|
+
eventHandler,
|
|
415
|
+
sourceTables
|
|
416
|
+
});
|
|
392
417
|
|
|
393
418
|
await connectionManager.query(`CREATE TABLE test_failure (id CHAR(36), description VARCHAR(100))`);
|
|
394
419
|
await connectionManager.query(`INSERT INTO test_failure(id, description) VALUES('${uuid()}','test_failure')`);
|
|
@@ -403,7 +428,11 @@ describe('BinlogListener tests', () => {
|
|
|
403
428
|
|
|
404
429
|
test('Unprocessed binlog event received for a dropped table', async () => {
|
|
405
430
|
const sourceTables = [new TablePattern(connectionManager.databaseName, 'test_failure')];
|
|
406
|
-
binLogListener = await createBinlogListener(
|
|
431
|
+
binLogListener = await createBinlogListener({
|
|
432
|
+
connectionManager,
|
|
433
|
+
eventHandler,
|
|
434
|
+
sourceTables
|
|
435
|
+
});
|
|
407
436
|
|
|
408
437
|
// If we process a binlog event for a table which has since been dropped, we expect the binlog listener to stop with an error
|
|
409
438
|
await connectionManager.query(`CREATE TABLE test_failure (id CHAR(36), description VARCHAR(100))`);
|
|
@@ -424,7 +453,11 @@ describe('BinlogListener tests', () => {
|
|
|
424
453
|
new TablePattern(connectionManager.databaseName, 'test_DATA'),
|
|
425
454
|
new TablePattern('multi_schema', 'test_DATA_multi')
|
|
426
455
|
];
|
|
427
|
-
binLogListener = await createBinlogListener(
|
|
456
|
+
binLogListener = await createBinlogListener({
|
|
457
|
+
connectionManager,
|
|
458
|
+
eventHandler,
|
|
459
|
+
sourceTables
|
|
460
|
+
});
|
|
428
461
|
await binLogListener.start();
|
|
429
462
|
|
|
430
463
|
// Default database insert into test_DATA
|
|
@@ -439,28 +472,6 @@ describe('BinlogListener tests', () => {
|
|
|
439
472
|
assertSchemaChange(eventHandler.schemaChanges[0], SchemaChangeType.DROP_TABLE, 'multi_schema', 'test_DATA_multi');
|
|
440
473
|
});
|
|
441
474
|
|
|
442
|
-
async function createBinlogListener(
|
|
443
|
-
sourceTables?: TablePattern[],
|
|
444
|
-
startPosition?: common.BinLogPosition
|
|
445
|
-
): Promise<BinLogListener> {
|
|
446
|
-
if (!sourceTables) {
|
|
447
|
-
sourceTables = [new TablePattern(connectionManager.databaseName, 'test_DATA')];
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
if (!startPosition) {
|
|
451
|
-
const fromGTID = await getFromGTID(connectionManager);
|
|
452
|
-
startPosition = fromGTID.position;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
return new BinLogListener({
|
|
456
|
-
connectionManager: connectionManager,
|
|
457
|
-
eventHandler: eventHandler,
|
|
458
|
-
startPosition: startPosition,
|
|
459
|
-
sourceTables: sourceTables,
|
|
460
|
-
serverId: createRandomServerId(1)
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
|
|
464
475
|
function assertSchemaChange(
|
|
465
476
|
change: SchemaChange,
|
|
466
477
|
type: SchemaChangeType,
|
|
@@ -477,14 +488,6 @@ describe('BinlogListener tests', () => {
|
|
|
477
488
|
}
|
|
478
489
|
});
|
|
479
490
|
|
|
480
|
-
async function getFromGTID(connectionManager: MySQLConnectionManager) {
|
|
481
|
-
const connection = await connectionManager.getConnection();
|
|
482
|
-
const fromGTID = await common.readExecutedGtid(connection);
|
|
483
|
-
connection.release();
|
|
484
|
-
|
|
485
|
-
return fromGTID;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
491
|
async function insertRows(connectionManager: MySQLConnectionManager, count: number) {
|
|
489
492
|
for (let i = 0; i < count; i++) {
|
|
490
493
|
await connectionManager.query(
|
|
@@ -500,45 +503,3 @@ async function updateRows(connectionManager: MySQLConnectionManager) {
|
|
|
500
503
|
async function deleteRows(connectionManager: MySQLConnectionManager) {
|
|
501
504
|
await connectionManager.query(`DELETE FROM test_DATA`);
|
|
502
505
|
}
|
|
503
|
-
|
|
504
|
-
class TestBinLogEventHandler implements BinLogEventHandler {
|
|
505
|
-
rowsWritten = 0;
|
|
506
|
-
rowsUpdated = 0;
|
|
507
|
-
rowsDeleted = 0;
|
|
508
|
-
commitCount = 0;
|
|
509
|
-
schemaChanges: SchemaChange[] = [];
|
|
510
|
-
|
|
511
|
-
unpause: ((value: void | PromiseLike<void>) => void) | undefined;
|
|
512
|
-
private pausedPromise: Promise<void> | undefined;
|
|
513
|
-
|
|
514
|
-
pause() {
|
|
515
|
-
this.pausedPromise = new Promise((resolve) => {
|
|
516
|
-
this.unpause = resolve;
|
|
517
|
-
});
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
async onWrite(rows: Row[], tableMap: TableMapEntry) {
|
|
521
|
-
if (this.pausedPromise) {
|
|
522
|
-
await this.pausedPromise;
|
|
523
|
-
}
|
|
524
|
-
this.rowsWritten = this.rowsWritten + rows.length;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
async onUpdate(afterRows: Row[], beforeRows: Row[], tableMap: TableMapEntry) {
|
|
528
|
-
this.rowsUpdated = this.rowsUpdated + afterRows.length;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
async onDelete(rows: Row[], tableMap: TableMapEntry) {
|
|
532
|
-
this.rowsDeleted = this.rowsDeleted + rows.length;
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
async onCommit(lsn: string) {
|
|
536
|
-
this.commitCount++;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
async onSchemaChange(change: SchemaChange) {
|
|
540
|
-
this.schemaChanges.push(change);
|
|
541
|
-
}
|
|
542
|
-
async onTransactionStart(options: { timestamp: Date }) {}
|
|
543
|
-
async onRotate() {}
|
|
544
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SqliteRow } from '@powersync/service-sync-rules';
|
|
1
|
+
import { SqliteInputRow, SqliteRow } from '@powersync/service-sync-rules';
|
|
2
2
|
import { afterAll, describe, expect, test } from 'vitest';
|
|
3
3
|
import { clearTestDb, TEST_CONNECTION_OPTIONS } from './util.js';
|
|
4
4
|
import { eventIsWriteMutation, eventIsXid } from '@module/replication/zongji/zongji-utils.js';
|
|
@@ -298,7 +298,7 @@ INSERT INTO test_data (
|
|
|
298
298
|
});
|
|
299
299
|
});
|
|
300
300
|
|
|
301
|
-
async function getDatabaseRows(connection: MySQLConnectionManager, tableName: string): Promise<
|
|
301
|
+
async function getDatabaseRows(connection: MySQLConnectionManager, tableName: string): Promise<SqliteInputRow[]> {
|
|
302
302
|
const [results, fields] = await connection.query(`SELECT * FROM ${tableName}`);
|
|
303
303
|
const columns = toColumnDescriptors(fields);
|
|
304
304
|
return results.map((row) => common.toSQLiteRow(row, columns));
|
|
@@ -307,15 +307,15 @@ async function getDatabaseRows(connection: MySQLConnectionManager, tableName: st
|
|
|
307
307
|
/**
|
|
308
308
|
* Return all the inserts from the first transaction in the binlog stream.
|
|
309
309
|
*/
|
|
310
|
-
async function getReplicatedRows(expectedTransactionsCount?: number): Promise<
|
|
311
|
-
let transformed:
|
|
310
|
+
async function getReplicatedRows(expectedTransactionsCount?: number): Promise<SqliteInputRow[]> {
|
|
311
|
+
let transformed: SqliteInputRow[] = [];
|
|
312
312
|
const zongji = new ZongJi({
|
|
313
313
|
host: TEST_CONNECTION_OPTIONS.hostname,
|
|
314
314
|
user: TEST_CONNECTION_OPTIONS.username,
|
|
315
315
|
password: TEST_CONNECTION_OPTIONS.password
|
|
316
316
|
});
|
|
317
317
|
|
|
318
|
-
const completionPromise = new Promise<
|
|
318
|
+
const completionPromise = new Promise<SqliteInputRow[]>((resolve, reject) => {
|
|
319
319
|
zongji.on('binlog', (evt: BinLogEvent) => {
|
|
320
320
|
try {
|
|
321
321
|
if (eventIsWriteMutation(evt)) {
|
|
@@ -652,12 +652,8 @@ function defineTests(factory: storage.TestStorageFactory) {
|
|
|
652
652
|
await connectionManager.query(`INSERT INTO ${testTable}(id, description) VALUES('t3','test3')`);
|
|
653
653
|
await connectionManager.query(`DROP TABLE ${testTable}`);
|
|
654
654
|
|
|
655
|
-
// Force a commit on the watched schema to advance the checkpoint
|
|
656
|
-
await connectionManager.query(`INSERT INTO test_data(id, description) VALUES('t1','test1')`);
|
|
657
|
-
|
|
658
655
|
const data = await context.getBucketData('global[]');
|
|
659
656
|
|
|
660
|
-
|
|
661
|
-
expect(data).toMatchObject([PUT_T1]);
|
|
657
|
+
expect(data).toMatchObject([]);
|
|
662
658
|
});
|
|
663
659
|
}
|
package/test/src/util.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as types from '@module/types/types.js';
|
|
2
|
-
import { getMySQLVersion, isVersionAtLeast } from '@module/utils/mysql-utils.js';
|
|
2
|
+
import { createRandomServerId, getMySQLVersion, isVersionAtLeast } from '@module/utils/mysql-utils.js';
|
|
3
3
|
import * as mongo_storage from '@powersync/service-module-mongodb-storage';
|
|
4
4
|
import * as postgres_storage from '@powersync/service-module-postgres-storage';
|
|
5
5
|
import mysqlPromise from 'mysql2/promise';
|
|
@@ -7,6 +7,10 @@ import { env } from './env.js';
|
|
|
7
7
|
import { describe, TestOptions } from 'vitest';
|
|
8
8
|
import { TestStorageFactory } from '@powersync/service-core';
|
|
9
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';
|
|
10
14
|
|
|
11
15
|
export const TEST_URI = env.MYSQL_TEST_URI;
|
|
12
16
|
|
|
@@ -58,3 +62,79 @@ export async function createTestDb(connectionManager: MySQLConnectionManager, db
|
|
|
58
62
|
await connectionManager.query(`DROP DATABASE IF EXISTS ${dbName}`);
|
|
59
63
|
await connectionManager.query(`CREATE DATABASE IF NOT EXISTS ${dbName}`);
|
|
60
64
|
}
|
|
65
|
+
|
|
66
|
+
export async function getFromGTID(connectionManager: MySQLConnectionManager) {
|
|
67
|
+
const connection = await connectionManager.getConnection();
|
|
68
|
+
const fromGTID = await common.readExecutedGtid(connection);
|
|
69
|
+
connection.release();
|
|
70
|
+
|
|
71
|
+
return fromGTID;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface CreateBinlogListenerParams {
|
|
75
|
+
connectionManager: MySQLConnectionManager;
|
|
76
|
+
eventHandler: BinLogEventHandler;
|
|
77
|
+
sourceTables: TablePattern[];
|
|
78
|
+
startGTID?: common.ReplicatedGTID;
|
|
79
|
+
}
|
|
80
|
+
export async function createBinlogListener(params: CreateBinlogListenerParams): Promise<BinLogListener> {
|
|
81
|
+
let { connectionManager, eventHandler, sourceTables, startGTID } = params;
|
|
82
|
+
|
|
83
|
+
if (!startGTID) {
|
|
84
|
+
startGTID = await getFromGTID(connectionManager);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return new BinLogListener({
|
|
88
|
+
connectionManager: connectionManager,
|
|
89
|
+
eventHandler: eventHandler,
|
|
90
|
+
startGTID: startGTID!,
|
|
91
|
+
sourceTables: sourceTables,
|
|
92
|
+
serverId: createRandomServerId(1)
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export class TestBinLogEventHandler implements BinLogEventHandler {
|
|
97
|
+
rowsWritten = 0;
|
|
98
|
+
rowsUpdated = 0;
|
|
99
|
+
rowsDeleted = 0;
|
|
100
|
+
commitCount = 0;
|
|
101
|
+
schemaChanges: SchemaChange[] = [];
|
|
102
|
+
lastKeepAlive: string | undefined;
|
|
103
|
+
|
|
104
|
+
unpause: ((value: void | PromiseLike<void>) => void) | undefined;
|
|
105
|
+
private pausedPromise: Promise<void> | undefined;
|
|
106
|
+
|
|
107
|
+
pause() {
|
|
108
|
+
this.pausedPromise = new Promise((resolve) => {
|
|
109
|
+
this.unpause = resolve;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async onWrite(rows: Row[], tableMap: TableMapEntry) {
|
|
114
|
+
if (this.pausedPromise) {
|
|
115
|
+
await this.pausedPromise;
|
|
116
|
+
}
|
|
117
|
+
this.rowsWritten = this.rowsWritten + rows.length;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async onUpdate(afterRows: Row[], beforeRows: Row[], tableMap: TableMapEntry) {
|
|
121
|
+
this.rowsUpdated = this.rowsUpdated + afterRows.length;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async onDelete(rows: Row[], tableMap: TableMapEntry) {
|
|
125
|
+
this.rowsDeleted = this.rowsDeleted + rows.length;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async onCommit(lsn: string) {
|
|
129
|
+
this.commitCount++;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async onSchemaChange(change: SchemaChange) {
|
|
133
|
+
this.schemaChanges.push(change);
|
|
134
|
+
}
|
|
135
|
+
async onTransactionStart(options: { timestamp: Date }) {}
|
|
136
|
+
async onRotate() {}
|
|
137
|
+
async onKeepAlive(lsn: string) {
|
|
138
|
+
this.lastKeepAlive = lsn;
|
|
139
|
+
}
|
|
140
|
+
}
|