Skip to content

Commit 941b166

Browse files
authored
Add type definitions and pause/resume functionality (#3)
Added typescript type definitions and the ability to pause / resume the binlog listener.
1 parent 6ee295c commit 941b166

File tree

12 files changed

+448
-202
lines changed

12 files changed

+448
-202
lines changed

.changeset/thick-carpets-shake.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@powersync/mysql-zongji': minor
3+
---
4+
5+
Added the functionality to pause / resume the zongji binlog listener
6+
Improved stop/start functionality to better handle some race conditions
7+
Added type definitions
8+
The first time a TableMap event is emitted, it will always be emitted, but subsequent events will only be emitted if the table map has changed.

.github/workflows/dev-packages.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
uses: actions/setup-node@v4
1818
with:
1919
node-version-file: '.nvmrc'
20-
- uses: pnpm/action-setup@v2
20+
- uses: pnpm/action-setup@v4
2121
name: Install pnpm
2222
with:
2323
version: 9

.github/workflows/test.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,14 @@ jobs:
2626
-e MYSQL_ROOT_PASSWORD=my_password \
2727
-p 3306:3306 \
2828
-d mysql:${{ matrix.mysql-version }} \
29-
--server-id=1 \
30-
--log-bin=/var/lib/mysql/mysql-bin.log \
31-
--binlog-format=row
29+
--log-bin=/var/lib/mysql/mysql-bin.log
3230
3331
- name: Setup NodeJS
3432
uses: actions/setup-node@v4
3533
with:
3634
node-version-file: '.nvmrc'
3735

38-
- uses: pnpm/action-setup@v2
36+
- uses: pnpm/action-setup@v4
3937
name: Install pnpm
4038
with:
4139
version: 9

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v20.12.2
1+
v22.14.0

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,9 @@ Neither method requires any arguments.
143143

144144
## Run Tests
145145

146-
- install [Docker](https://www.docker.com/community-edition#download)
147-
- run `docker-compose up` and then `./docker-test.sh`
146+
- Install [Docker](https://www.docker.com/community-edition#download)
147+
- Run `docker-compose up` and then `./docker-test.sh`
148+
- Some tests can be run directly, but some of the types.js tests pertaining to dates are affected by the host's timezone and are consequently brittle.
148149

149150
## References
150151

@@ -157,7 +158,7 @@ The following resources provided valuable information that greatly assisted in c
157158
- https://kkaefer.com/node-cpp-modules/
158159
- https://dev.mysql.com/doc/internals/en/replication-protocol.html
159160
- https://web.archive.org/web/20200201195450/https://www.cs.wichita.edu/~chang/lecture/cs742/program/how-mysql-c-api.html
160-
- https://github.com/jeremycole/mysql_binlog (Ruby implemenation of MySQL binlog parser)
161+
- https://github.com/jeremycole/mysql_binlog (Ruby implementation of MySQL binlog parser)
161162
- https://dev.mysql.com/doc/internals/en/date-and-time-data-type-representation.html
162163

163164
## License

docker-test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
MYSQL_HOSTS="mysql80 mysql84"
33

44
for hostname in ${MYSQL_HOSTS}; do
5-
echo $hostname + node 20
5+
echo $hostname + node 22
66
docker run -it --network=powersync-mysql-zongji_default -e MYSQL_HOST=$hostname -w /build -v $PWD:/build node:20 npm test
77
done

index.js

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ function ZongJi(dsn) {
2222
this.ctrlCallbacks = [];
2323
this.tableMap = {};
2424
this.ready = false;
25+
this.stopped = false;
2526
this.useChecksum = false;
2627

2728
this._establishConnection(dsn);
@@ -192,6 +193,9 @@ ZongJi.prototype.start = function (options = {}) {
192193
this._filters(options);
193194

194195
const testChecksum = (resolve, reject) => {
196+
if (this.stopped) {
197+
resolve();
198+
}
195199
this._isChecksumEnabled((err, checksumEnabled) => {
196200
if (err) {
197201
reject(err);
@@ -203,6 +207,9 @@ ZongJi.prototype.start = function (options = {}) {
203207
};
204208

205209
const findBinlogEnd = (resolve, reject) => {
210+
if (this.stopped) {
211+
resolve();
212+
}
206213
this._findBinlogEnd((err, result) => {
207214
if (err) {
208215
return reject(err);
@@ -240,9 +247,8 @@ ZongJi.prototype.start = function (options = {}) {
240247
this.emit('binlog', event);
241248
this.connection.resume();
242249
});
243-
return;
244250
}
245-
break;
251+
return;
246252
}
247253
case 'Rotate':
248254
if (this.options.filename !== event.binlogName) {
@@ -263,25 +269,41 @@ ZongJi.prototype.start = function (options = {}) {
263269
Promise.all(promises)
264270
.then(() => {
265271
this.BinlogClass = initBinlogClass(this);
266-
this.ready = true;
267-
this.emit('ready');
268-
269-
this.connection._protocol._enqueue(new this.BinlogClass(binlogHandler));
272+
if (!this.stopped) {
273+
this.connection._protocol._enqueue(new this.BinlogClass(binlogHandler));
274+
this.ready = true;
275+
this.emit('ready');
276+
}
270277
})
271278
.catch((err) => {
272279
this.emit('error', err);
273280
});
274281
};
275282

276283
ZongJi.prototype.stop = function () {
277-
// Binary log connection does not end with destroy()
278-
this.connection.destroy();
279-
this.ctrlConnection.query('KILL ' + this.connection.threadId, () => {
280-
if (this.ctrlConnectionOwner) {
281-
this.ctrlConnection.destroy();
282-
}
283-
this.emit('stopped');
284-
});
284+
if (!this.stopped) {
285+
this.stopped = true;
286+
// Binary log connection does not end with destroy()
287+
this.connection.destroy();
288+
this.ctrlConnection.query('KILL ' + this.connection.threadId, (err, result) => {
289+
if (this.ctrlConnectionOwner) {
290+
this.ctrlConnection.destroy();
291+
}
292+
this.emit('stopped');
293+
});
294+
}
295+
};
296+
297+
ZongJi.prototype.pause = function () {
298+
if (!this.stopped) {
299+
this.connection.pause();
300+
}
301+
};
302+
303+
ZongJi.prototype.resume = function () {
304+
if (!this.stopped) {
305+
this.connection.resume();
306+
}
285307
};
286308

287309
// It includes every events by default.
@@ -312,3 +334,4 @@ ZongJi.prototype._skipSchema = function (database, table) {
312334
};
313335

314336
module.exports = ZongJi;
337+
module.exports.ZongJi = ZongJi;

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"version": "0.1.0",
44
"description": "A MySQL 8.0 >= compatible fork of ZongJi - a MySQL binlog listener for Node.js.",
55
"main": "index.js",
6+
"types": "types/index.d.ts",
67
"directories": {
78
"test": "test"
89
},
@@ -35,15 +36,15 @@
3536
],
3637
"license": "MIT",
3738
"engines": {
38-
"node": ">=20.0.0"
39+
"node": ">=22.0.0"
3940
},
4041
"devDependencies": {
41-
"@changesets/cli": "^2.27.3",
42-
"prettier": "^2.8.8",
42+
"@changesets/cli": "^2.29.4",
43+
"prettier": "^3.5.3",
4344
"tap": "^21.0.1"
4445
},
4546
"dependencies": {
46-
"big-integer": "1.6.51",
47+
"big-integer": "1.6.52",
4748
"iconv-lite": "0.6.3",
4849
"@vlasky/mysql": "^2.18.6"
4950
}

0 commit comments

Comments
 (0)