@powersync/service-module-mysql 0.6.5 → 0.7.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.
- package/CHANGELOG.md +30 -0
- package/dist/api/MySQLRouteAPIAdapter.d.ts +1 -1
- package/dist/api/MySQLRouteAPIAdapter.js +1 -1
- package/dist/api/MySQLRouteAPIAdapter.js.map +1 -1
- package/dist/replication/BinLogReplicationJob.d.ts +2 -0
- package/dist/replication/BinLogReplicationJob.js +10 -3
- package/dist/replication/BinLogReplicationJob.js.map +1 -1
- package/dist/replication/BinLogReplicator.d.ts +1 -0
- package/dist/replication/BinLogReplicator.js +22 -0
- package/dist/replication/BinLogReplicator.js.map +1 -1
- package/dist/replication/BinLogStream.d.ts +17 -1
- package/dist/replication/BinLogStream.js +126 -174
- package/dist/replication/BinLogStream.js.map +1 -1
- package/dist/replication/MySQLConnectionManager.d.ts +1 -1
- package/dist/replication/MySQLConnectionManager.js +2 -1
- package/dist/replication/MySQLConnectionManager.js.map +1 -1
- package/dist/replication/zongji/BinLogListener.d.ts +54 -0
- package/dist/replication/zongji/BinLogListener.js +192 -0
- package/dist/replication/zongji/BinLogListener.js.map +1 -0
- package/dist/replication/zongji/zongji-utils.d.ts +5 -4
- package/dist/replication/zongji/zongji-utils.js +3 -0
- package/dist/replication/zongji/zongji-utils.js.map +1 -1
- package/dist/types/types.d.ts +2 -0
- package/dist/types/types.js +5 -1
- package/dist/types/types.js.map +1 -1
- package/dist/utils/mysql-utils.js +1 -0
- package/dist/utils/mysql-utils.js.map +1 -1
- package/package.json +9 -9
- package/src/api/MySQLRouteAPIAdapter.ts +1 -1
- package/src/replication/BinLogReplicationJob.ts +11 -3
- package/src/replication/BinLogReplicator.ts +25 -0
- package/src/replication/BinLogStream.ts +151 -201
- package/src/replication/MySQLConnectionManager.ts +2 -1
- package/src/replication/zongji/BinLogListener.ts +243 -0
- package/src/replication/zongji/zongji-utils.ts +10 -5
- package/src/types/types.ts +8 -1
- package/src/utils/mysql-utils.ts +1 -0
- package/test/src/BinLogListener.test.ts +161 -0
- package/test/src/BinLogStream.test.ts +4 -9
- package/test/src/mysql-to-sqlite.test.ts +1 -1
- package/test/src/util.ts +12 -0
- package/test/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/src/replication/zongji/zongji.d.ts +0 -129
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import * as common from '../../common/common-index.js';
|
|
2
|
+
import async from 'async';
|
|
3
|
+
import * as zongji_utils from './zongji-utils.js';
|
|
4
|
+
import { logger as defaultLogger } from '@powersync/lib-services-framework';
|
|
5
|
+
// Maximum time the processing queue can be paused before resuming automatically
|
|
6
|
+
// MySQL server will automatically terminate replication connections after 60 seconds of inactivity, so this guards against that.
|
|
7
|
+
const MAX_QUEUE_PAUSE_TIME_MS = 45_000;
|
|
8
|
+
/**
|
|
9
|
+
* Wrapper class for the Zongji BinLog listener. Internally handles the creation and management of the listener and posts
|
|
10
|
+
* events on the provided BinLogEventHandler.
|
|
11
|
+
*/
|
|
12
|
+
export class BinLogListener {
|
|
13
|
+
options;
|
|
14
|
+
connectionManager;
|
|
15
|
+
eventHandler;
|
|
16
|
+
binLogPosition;
|
|
17
|
+
currentGTID;
|
|
18
|
+
logger;
|
|
19
|
+
zongji;
|
|
20
|
+
processingQueue;
|
|
21
|
+
/**
|
|
22
|
+
* The combined size in bytes of all the binlog events currently in the processing queue.
|
|
23
|
+
*/
|
|
24
|
+
queueMemoryUsage;
|
|
25
|
+
constructor(options) {
|
|
26
|
+
this.options = options;
|
|
27
|
+
this.logger = options.logger ?? defaultLogger;
|
|
28
|
+
this.connectionManager = options.connectionManager;
|
|
29
|
+
this.eventHandler = options.eventHandler;
|
|
30
|
+
this.binLogPosition = options.startPosition;
|
|
31
|
+
this.currentGTID = null;
|
|
32
|
+
this.processingQueue = async.queue(this.createQueueWorker(), 1);
|
|
33
|
+
this.queueMemoryUsage = 0;
|
|
34
|
+
this.zongji = this.createZongjiListener();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The queue memory limit in bytes as defined in the connection options.
|
|
38
|
+
* @private
|
|
39
|
+
*/
|
|
40
|
+
get queueMemoryLimit() {
|
|
41
|
+
return this.connectionManager.options.binlog_queue_memory_limit * 1024 * 1024;
|
|
42
|
+
}
|
|
43
|
+
async start() {
|
|
44
|
+
if (this.isStopped) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this.logger.info(`Starting replication. Created replica client with serverId:${this.options.serverId}`);
|
|
48
|
+
this.zongji.start({
|
|
49
|
+
// We ignore the unknown/heartbeat event since it currently serves no purpose other than to keep the connection alive
|
|
50
|
+
// tablemap events always need to be included for the other row events to work
|
|
51
|
+
includeEvents: ['tablemap', 'writerows', 'updaterows', 'deleterows', 'xid', 'rotate', 'gtidlog'],
|
|
52
|
+
includeSchema: { [this.connectionManager.databaseName]: this.options.includedTables },
|
|
53
|
+
filename: this.binLogPosition.filename,
|
|
54
|
+
position: this.binLogPosition.offset,
|
|
55
|
+
serverId: this.options.serverId
|
|
56
|
+
});
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
// Handle an edge case where the listener has already been stopped before completing startup
|
|
59
|
+
if (this.isStopped) {
|
|
60
|
+
this.logger.info('BinLog listener was stopped before startup completed.');
|
|
61
|
+
resolve();
|
|
62
|
+
}
|
|
63
|
+
this.zongji.on('error', (error) => {
|
|
64
|
+
if (!this.isStopped) {
|
|
65
|
+
this.logger.error('Binlog listener error:', error);
|
|
66
|
+
this.stop();
|
|
67
|
+
reject(error);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this.logger.warn('Binlog listener error during shutdown:', error);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
this.processingQueue.error((error) => {
|
|
74
|
+
if (!this.isStopped) {
|
|
75
|
+
this.logger.error('BinlogEvent processing error:', error);
|
|
76
|
+
this.stop();
|
|
77
|
+
reject(error);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
this.logger.warn('BinlogEvent processing error during shutdown:', error);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
this.zongji.on('stopped', () => {
|
|
84
|
+
resolve();
|
|
85
|
+
this.logger.info('BinLog listener stopped. Replication ended.');
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
stop() {
|
|
90
|
+
if (!this.isStopped) {
|
|
91
|
+
this.zongji.stop();
|
|
92
|
+
this.processingQueue.kill();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
get isStopped() {
|
|
96
|
+
return this.zongji.stopped;
|
|
97
|
+
}
|
|
98
|
+
createZongjiListener() {
|
|
99
|
+
const zongji = this.connectionManager.createBinlogListener();
|
|
100
|
+
zongji.on('binlog', async (evt) => {
|
|
101
|
+
this.logger.info(`Received Binlog event:${evt.getEventName()}`);
|
|
102
|
+
this.processingQueue.push(evt);
|
|
103
|
+
this.queueMemoryUsage += evt.size;
|
|
104
|
+
// When the processing queue grows past the threshold, we pause the binlog listener
|
|
105
|
+
if (this.isQueueOverCapacity()) {
|
|
106
|
+
this.logger.info(`Binlog processing queue has reached its memory limit of [${this.connectionManager.options.binlog_queue_memory_limit}MB]. Pausing Binlog listener.`);
|
|
107
|
+
zongji.pause();
|
|
108
|
+
const resumeTimeoutPromise = new Promise((resolve) => {
|
|
109
|
+
setTimeout(() => resolve('timeout'), MAX_QUEUE_PAUSE_TIME_MS);
|
|
110
|
+
});
|
|
111
|
+
await Promise.race([this.processingQueue.empty(), resumeTimeoutPromise]);
|
|
112
|
+
this.logger.info(`Binlog processing queue backlog cleared. Resuming Binlog listener.`);
|
|
113
|
+
zongji.resume();
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
zongji.on('ready', async () => {
|
|
117
|
+
// Set a heartbeat interval for the Zongji replication connection
|
|
118
|
+
// Zongji does not explicitly handle the heartbeat events - they are categorized as event:unknown
|
|
119
|
+
// The heartbeat events are enough to keep the connection alive for setTimeout to work on the socket.
|
|
120
|
+
await new Promise((resolve, reject) => {
|
|
121
|
+
this.zongji.connection.query(
|
|
122
|
+
// In nanoseconds, 10^9 = 1s
|
|
123
|
+
'set @master_heartbeat_period=28*1000000000', (error, results, fields) => {
|
|
124
|
+
if (error) {
|
|
125
|
+
reject(error);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
this.logger.info('Successfully set up replication connection heartbeat...');
|
|
129
|
+
resolve(results);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
// The _socket member is only set after a query is run on the connection, so we set the timeout after setting the heartbeat.
|
|
134
|
+
// The timeout here must be greater than the master_heartbeat_period.
|
|
135
|
+
const socket = this.zongji.connection._socket;
|
|
136
|
+
socket.setTimeout(60_000, () => {
|
|
137
|
+
this.logger.info('Destroying socket due to replication connection timeout.');
|
|
138
|
+
socket.destroy(new Error('Replication connection timeout.'));
|
|
139
|
+
});
|
|
140
|
+
this.logger.info(`BinLog listener setup complete. Reading binlog from: ${this.binLogPosition.filename}:${this.binLogPosition.offset}`);
|
|
141
|
+
});
|
|
142
|
+
return zongji;
|
|
143
|
+
}
|
|
144
|
+
createQueueWorker() {
|
|
145
|
+
return async (evt) => {
|
|
146
|
+
switch (true) {
|
|
147
|
+
case zongji_utils.eventIsGTIDLog(evt):
|
|
148
|
+
this.currentGTID = common.ReplicatedGTID.fromBinLogEvent({
|
|
149
|
+
raw_gtid: {
|
|
150
|
+
server_id: evt.serverId,
|
|
151
|
+
transaction_range: evt.transactionRange
|
|
152
|
+
},
|
|
153
|
+
position: {
|
|
154
|
+
filename: this.binLogPosition.filename,
|
|
155
|
+
offset: evt.nextPosition
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
await this.eventHandler.onTransactionStart({ timestamp: new Date(evt.timestamp) });
|
|
159
|
+
break;
|
|
160
|
+
case zongji_utils.eventIsRotation(evt):
|
|
161
|
+
this.binLogPosition.filename = evt.binlogName;
|
|
162
|
+
this.binLogPosition.offset = evt.position;
|
|
163
|
+
await this.eventHandler.onRotate();
|
|
164
|
+
break;
|
|
165
|
+
case zongji_utils.eventIsWriteMutation(evt):
|
|
166
|
+
await this.eventHandler.onWrite(evt.rows, evt.tableMap[evt.tableId]);
|
|
167
|
+
break;
|
|
168
|
+
case zongji_utils.eventIsUpdateMutation(evt):
|
|
169
|
+
await this.eventHandler.onUpdate(evt.rows.map((row) => row.after), evt.rows.map((row) => row.before), evt.tableMap[evt.tableId]);
|
|
170
|
+
break;
|
|
171
|
+
case zongji_utils.eventIsDeleteMutation(evt):
|
|
172
|
+
await this.eventHandler.onDelete(evt.rows, evt.tableMap[evt.tableId]);
|
|
173
|
+
break;
|
|
174
|
+
case zongji_utils.eventIsXid(evt):
|
|
175
|
+
const LSN = new common.ReplicatedGTID({
|
|
176
|
+
raw_gtid: this.currentGTID.raw,
|
|
177
|
+
position: {
|
|
178
|
+
filename: this.binLogPosition.filename,
|
|
179
|
+
offset: evt.nextPosition
|
|
180
|
+
}
|
|
181
|
+
}).comparable;
|
|
182
|
+
await this.eventHandler.onCommit(LSN);
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
this.queueMemoryUsage -= evt.size;
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
isQueueOverCapacity() {
|
|
189
|
+
return this.queueMemoryUsage >= this.queueMemoryLimit;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=BinLogListener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BinLogListener.js","sourceRoot":"","sources":["../../../src/replication/zongji/BinLogListener.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { BinLogEvent, BinLogGTIDLogEvent,
|
|
1
|
+
import { BinLogEvent, BinLogGTIDLogEvent, BinLogRowEvent, BinLogRotationEvent, BinLogTableMapEvent, BinLogRowUpdateEvent, BinLogXidEvent } from '@powersync/mysql-zongji';
|
|
2
2
|
export declare function eventIsGTIDLog(event: BinLogEvent): event is BinLogGTIDLogEvent;
|
|
3
|
+
export declare function eventIsTableMap(event: BinLogEvent): event is BinLogTableMapEvent;
|
|
3
4
|
export declare function eventIsXid(event: BinLogEvent): event is BinLogXidEvent;
|
|
4
5
|
export declare function eventIsRotation(event: BinLogEvent): event is BinLogRotationEvent;
|
|
5
|
-
export declare function eventIsWriteMutation(event: BinLogEvent): event is
|
|
6
|
-
export declare function eventIsDeleteMutation(event: BinLogEvent): event is
|
|
7
|
-
export declare function eventIsUpdateMutation(event: BinLogEvent): event is
|
|
6
|
+
export declare function eventIsWriteMutation(event: BinLogEvent): event is BinLogRowEvent;
|
|
7
|
+
export declare function eventIsDeleteMutation(event: BinLogEvent): event is BinLogRowEvent;
|
|
8
|
+
export declare function eventIsUpdateMutation(event: BinLogEvent): event is BinLogRowUpdateEvent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zongji-utils.js","sourceRoot":"","sources":["../../../src/replication/zongji/zongji-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"zongji-utils.js","sourceRoot":"","sources":["../../../src/replication/zongji/zongji-utils.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,cAAc,CAAC,KAAkB;IAC/C,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,SAAS,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,UAAU,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAkB;IAC3C,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,KAAK,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,QAAQ,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAkB;IACrD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,WAAW,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAkB;IACtD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,YAAY,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAkB;IACtD,OAAO,KAAK,CAAC,YAAY,EAAE,IAAI,YAAY,CAAC;AAC9C,CAAC"}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export interface NormalizedMySQLConnectionConfig {
|
|
|
14
14
|
client_certificate?: string;
|
|
15
15
|
client_private_key?: string;
|
|
16
16
|
lookup?: LookupFunction;
|
|
17
|
+
binlog_queue_memory_limit: number;
|
|
17
18
|
}
|
|
18
19
|
export declare const MySQLConnectionConfig: t.Intersection<t.Codec<{
|
|
19
20
|
type: string;
|
|
@@ -38,6 +39,7 @@ export declare const MySQLConnectionConfig: t.Intersection<t.Codec<{
|
|
|
38
39
|
client_certificate: t.OptionalCodec<t.Codec<string, string, string, t.CodecProps>>;
|
|
39
40
|
client_private_key: t.OptionalCodec<t.Codec<string, string, string, t.CodecProps>>;
|
|
40
41
|
reject_ip_ranges: t.OptionalCodec<t.Codec<string[], string[], string, t.CodecProps>>;
|
|
42
|
+
binlog_queue_memory_limit: t.OptionalCodec<t.Codec<number, number, string, t.CodecProps>>;
|
|
41
43
|
}>>;
|
|
42
44
|
/**
|
|
43
45
|
* Config input specified when starting services
|
package/dist/types/types.js
CHANGED
|
@@ -15,7 +15,9 @@ export const MySQLConnectionConfig = service_types.configFile.DataSourceConfig.a
|
|
|
15
15
|
cacert: t.string.optional(),
|
|
16
16
|
client_certificate: t.string.optional(),
|
|
17
17
|
client_private_key: t.string.optional(),
|
|
18
|
-
reject_ip_ranges: t.array(t.string).optional()
|
|
18
|
+
reject_ip_ranges: t.array(t.string).optional(),
|
|
19
|
+
// The combined size of binlog events that can be queued in memory before throttling is applied.
|
|
20
|
+
binlog_queue_memory_limit: t.number.optional()
|
|
19
21
|
}));
|
|
20
22
|
/**
|
|
21
23
|
* Validate and normalize connection options.
|
|
@@ -61,6 +63,8 @@ export function normalizeConnectionConfig(options) {
|
|
|
61
63
|
username,
|
|
62
64
|
password,
|
|
63
65
|
server_id: options.server_id ?? 1,
|
|
66
|
+
// Binlog processing queue memory limit before throttling is applied.
|
|
67
|
+
binlog_queue_memory_limit: options.binlog_queue_memory_limit ?? 50,
|
|
64
68
|
lookup
|
|
65
69
|
};
|
|
66
70
|
}
|
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,qBAAqB,GAAG,OAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysql-utils.js","sourceRoot":"","sources":["../../src/utils/mysql-utils.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mysql-utils.js","sourceRoot":"","sources":["../../src/utils/mysql-utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@powersync/service-module-mysql",
|
|
3
3
|
"repository": "https://github.com/powersync-ja/powersync-service",
|
|
4
4
|
"types": "dist/index.d.ts",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.7.1",
|
|
6
6
|
"license": "FSL-1.1-Apache-2.0",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"type": "module",
|
|
@@ -22,25 +22,25 @@
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@powersync/mysql-zongji": "
|
|
25
|
+
"@powersync/mysql-zongji": "0.2.0",
|
|
26
26
|
"async": "^3.2.4",
|
|
27
27
|
"mysql2": "^3.11.0",
|
|
28
28
|
"semver": "^7.5.4",
|
|
29
29
|
"ts-codec": "^1.3.0",
|
|
30
30
|
"uri-js": "^4.4.1",
|
|
31
31
|
"uuid": "^11.1.0",
|
|
32
|
-
"@powersync/lib-services-framework": "0.
|
|
33
|
-
"@powersync/service-core": "1.
|
|
34
|
-
"@powersync/service-jsonbig": "0.17.10",
|
|
32
|
+
"@powersync/lib-services-framework": "0.7.0",
|
|
33
|
+
"@powersync/service-core": "1.13.1",
|
|
35
34
|
"@powersync/service-sync-rules": "0.27.0",
|
|
36
|
-
"@powersync/service-types": "0.
|
|
35
|
+
"@powersync/service-types": "0.12.0",
|
|
36
|
+
"@powersync/service-jsonbig": "0.17.10"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/async": "^3.2.24",
|
|
40
40
|
"@types/semver": "^7.5.4",
|
|
41
|
-
"@powersync/service-core-tests": "0.
|
|
42
|
-
"@powersync/service-module-mongodb-storage": "0.
|
|
43
|
-
"@powersync/service-module-postgres-storage": "0.
|
|
41
|
+
"@powersync/service-core-tests": "0.10.1",
|
|
42
|
+
"@powersync/service-module-mongodb-storage": "0.10.1",
|
|
43
|
+
"@powersync/service-module-postgres-storage": "0.8.1"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "tsc -b",
|
|
@@ -249,7 +249,7 @@ export class MySQLRouteAPIAdapter implements api.RouteAPI {
|
|
|
249
249
|
};
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
async
|
|
252
|
+
async getReplicationLagBytes(options: api.ReplicationLagOptions): Promise<number | undefined> {
|
|
253
253
|
const { bucketStorage } = options;
|
|
254
254
|
const lastCheckpoint = await bucketStorage.getCheckpoint();
|
|
255
255
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { container } from '@powersync/lib-services-framework';
|
|
1
|
+
import { container, logger as defaultLogger } from '@powersync/lib-services-framework';
|
|
2
2
|
import { replication } from '@powersync/service-core';
|
|
3
3
|
import { BinlogConfigurationError, BinLogStream } from './BinLogStream.js';
|
|
4
4
|
import { MySQLConnectionManagerFactory } from './MySQLConnectionManagerFactory.js';
|
|
@@ -9,9 +9,11 @@ export interface BinLogReplicationJobOptions extends replication.AbstractReplica
|
|
|
9
9
|
|
|
10
10
|
export class BinLogReplicationJob extends replication.AbstractReplicationJob {
|
|
11
11
|
private connectionFactory: MySQLConnectionManagerFactory;
|
|
12
|
+
private lastStream: BinLogStream | null = null;
|
|
12
13
|
|
|
13
14
|
constructor(options: BinLogReplicationJobOptions) {
|
|
14
15
|
super(options);
|
|
16
|
+
this.logger = defaultLogger.child({ prefix: `[powersync_${this.options.storage.group_id}] ` });
|
|
15
17
|
this.connectionFactory = options.connectionFactory;
|
|
16
18
|
}
|
|
17
19
|
|
|
@@ -31,7 +33,7 @@ export class BinLogReplicationJob extends replication.AbstractReplicationJob {
|
|
|
31
33
|
replication_slot: this.slot_name
|
|
32
34
|
}
|
|
33
35
|
});
|
|
34
|
-
this.logger.error(`Replication failed
|
|
36
|
+
this.logger.error(`Replication failed`, e);
|
|
35
37
|
} finally {
|
|
36
38
|
this.abortController.abort();
|
|
37
39
|
}
|
|
@@ -61,17 +63,19 @@ export class BinLogReplicationJob extends replication.AbstractReplicationJob {
|
|
|
61
63
|
return;
|
|
62
64
|
}
|
|
63
65
|
const stream = new BinLogStream({
|
|
66
|
+
logger: this.logger,
|
|
64
67
|
abortSignal: this.abortController.signal,
|
|
65
68
|
storage: this.options.storage,
|
|
66
69
|
metrics: this.options.metrics,
|
|
67
70
|
connections: connectionManager
|
|
68
71
|
});
|
|
72
|
+
this.lastStream = stream;
|
|
69
73
|
await stream.replicate();
|
|
70
74
|
} catch (e) {
|
|
71
75
|
if (this.abortController.signal.aborted) {
|
|
72
76
|
return;
|
|
73
77
|
}
|
|
74
|
-
this.logger.error(`
|
|
78
|
+
this.logger.error(`Replication error`, e);
|
|
75
79
|
if (e.cause != null) {
|
|
76
80
|
this.logger.error(`cause`, e.cause);
|
|
77
81
|
}
|
|
@@ -92,4 +96,8 @@ export class BinLogReplicationJob extends replication.AbstractReplicationJob {
|
|
|
92
96
|
await connectionManager.end();
|
|
93
97
|
}
|
|
94
98
|
}
|
|
99
|
+
|
|
100
|
+
async getReplicationLagMillis(): Promise<number | undefined> {
|
|
101
|
+
return this.lastStream?.getReplicationLagMillis();
|
|
102
|
+
}
|
|
95
103
|
}
|
|
@@ -38,4 +38,29 @@ export class BinLogReplicator extends replication.AbstractReplicator<BinLogRepli
|
|
|
38
38
|
async testConnection() {
|
|
39
39
|
return await MySQLModule.testConnection(this.connectionFactory.connectionConfig);
|
|
40
40
|
}
|
|
41
|
+
|
|
42
|
+
async getReplicationLagMillis(): Promise<number | undefined> {
|
|
43
|
+
const lag = await super.getReplicationLagMillis();
|
|
44
|
+
if (lag != null) {
|
|
45
|
+
return lag;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Booting or in an error loop. Check last active replication status.
|
|
49
|
+
// This includes sync rules in an ERROR state.
|
|
50
|
+
const content = await this.storage.getActiveSyncRulesContent();
|
|
51
|
+
if (content == null) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
// Measure the lag from the last commit or keepalive timestamp.
|
|
55
|
+
// This is not 100% accurate since it is the commit time in the storage db rather than
|
|
56
|
+
// the source db, but it's the best we currently have for mysql.
|
|
57
|
+
const checkpointTs = content.last_checkpoint_ts?.getTime() ?? 0;
|
|
58
|
+
const keepaliveTs = content.last_keepalive_ts?.getTime() ?? 0;
|
|
59
|
+
const latestTs = Math.max(checkpointTs, keepaliveTs);
|
|
60
|
+
if (latestTs != 0) {
|
|
61
|
+
return Date.now() - latestTs;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
41
66
|
}
|