diff --git a/.changeset/shy-kings-eat.md b/.changeset/shy-kings-eat.md new file mode 100644 index 0000000..aa6a68b --- /dev/null +++ b/.changeset/shy-kings-eat.md @@ -0,0 +1,8 @@ +--- +'@powersync/mysql-zongji': minor +--- + +Added binlog hearbeat parsing and type definitions +Updated the CodeEvent enum to include the newer MySQL BinLog types + +Exposed startAtEnd option in the Zongji start options. Thank you @svenpaulsen! \ No newline at end of file diff --git a/lib/binlog_event.js b/lib/binlog_event.js index da76892..06ff64a 100644 --- a/lib/binlog_event.js +++ b/lib/binlog_event.js @@ -28,6 +28,32 @@ BinlogEvent.prototype._readTableId = function (parser) { this.tableId = Common.parseUInt48(parser); }; +function Heartbeat(parser) { + BinlogEvent.apply(this, arguments); + this.binlogName = parser.parseString(this.size); +} +util.inherits(Heartbeat, BinlogEvent); + +Heartbeat.prototype.dump = function () { + console.log('=== %s ===', this.getTypeName()); + console.log('Event size: %d', this.size); + console.log('Current binlog file: %s', this.binlogName); +}; + +function Heartbeat_V2(parser) { + BinlogEvent.apply(this, arguments); + this.binlogName = parser.parseString(this.size - 8); + this.position = Common.parseUInt64(parser); +} +util.inherits(Heartbeat_V2, BinlogEvent); + +Heartbeat_V2.prototype.dump = function () { + console.log('=== %s ===', this.getTypeName()); + console.log('Event size: %d', this.size); + console.log('Current binlog file: %s', this.binlogName); + console.log('Position: %d', this.position); +}; + /* Change MySQL bin log file * Attributes: * position: Position inside next binlog @@ -303,6 +329,8 @@ function Unknown() { util.inherits(Unknown, BinlogEvent); exports.BinlogEvent = BinlogEvent; +exports.Heartbeat = Heartbeat; +exports.Heartbeat_V2 = Heartbeat_V2; exports.Rotate = Rotate; exports.Format = Format; exports.Query = Query; diff --git a/lib/code_map.js b/lib/code_map.js index 4ca1d20..e12e103 100644 --- a/lib/code_map.js +++ b/lib/code_map.js @@ -1,43 +1,51 @@ const events = require('./binlog_event'); const rowsEvents = require('./rows_event'); +// Mirrors the Binlog Event Type enum from here: https://dev.mysql.com/doc/dev/mysql-server/9.3.0/binlog__event_8h_source.html const CodeEvent = [ - 'UNKNOWN_EVENT', - 'START_EVENT_V3', - 'QUERY_EVENT', - 'STOP_EVENT', - 'ROTATE_EVENT', - 'INTVAR_EVENT', - 'LOAD_EVENT', - 'SLAVE_EVENT', - 'CREATE_FILE_EVENT', - 'APPEND_BLOCK_EVENT', - 'EXEC_LOAD_EVENT', - 'DELETE_FILE_EVENT', - 'NEW_LOAD_EVENT', - 'RAND_EVENT', - 'USER_VAR_EVENT', - 'FORMAT_DESCRIPTION_EVENT', - 'XID_EVENT', - 'BEGIN_LOAD_QUERY_EVENT', - 'EXECUTE_LOAD_QUERY_EVENT', - 'TABLE_MAP_EVENT', - 'PRE_GA_DELETE_ROWS_EVENT', - 'PRE_GA_UPDATE_ROWS_EVENT', - 'PRE_GA_WRITE_ROWS_EVENT', - 'WRITE_ROWS_EVENT_V1', - 'UPDATE_ROWS_EVENT_V1', - 'DELETE_ROWS_EVENT_V1', - 'INCIDENT_EVENT', - 'HEARTBEAT_LOG_EVENT', - 'IGNORABLE_LOG_EVENT', - 'ROWS_QUERY_LOG_EVENT', - 'WRITE_ROWS_EVENT_V2', - 'UPDATE_ROWS_EVENT_V2', - 'DELETE_ROWS_EVENT_V2', - 'GTID_LOG_EVENT', - 'ANONYMOUS_GTID_LOG_EVENT', - 'PREVIOUS_GTIDS_LOG_EVENT' + 'UNKNOWN_EVENT', // 0 + 'START_EVENT_V3', // 1 + 'QUERY_EVENT', // 2 + 'STOP_EVENT', // 3 + 'ROTATE_EVENT', // 4 + 'INTVAR_EVENT', // 5 + 'LOAD_EVENT', // 6 + 'SLAVE_EVENT', // 7 + 'CREATE_FILE_EVENT', // 8 + 'APPEND_BLOCK_EVENT', // 9 + 'EXEC_LOAD_EVENT', // 10 + 'DELETE_FILE_EVENT', // 11 + 'NEW_LOAD_EVENT', // 12 + 'RAND_EVENT', // 13 + 'USER_VAR_EVENT', // 14 + 'FORMAT_DESCRIPTION_EVENT', // 15 + 'XID_EVENT', // 16 + 'BEGIN_LOAD_QUERY_EVENT', // 17 + 'EXECUTE_LOAD_QUERY_EVENT', // 18 + 'TABLE_MAP_EVENT', // 19 + 'PRE_GA_DELETE_ROWS_EVENT', // 20 + 'PRE_GA_UPDATE_ROWS_EVENT', // 21 + 'PRE_GA_WRITE_ROWS_EVENT', // 22 + 'WRITE_ROWS_EVENT_V1', // 23 + 'UPDATE_ROWS_EVENT_V1', // 24 + 'DELETE_ROWS_EVENT_V1', // 25 + 'INCIDENT_EVENT', // 26 + 'HEARTBEAT_LOG_EVENT', // 27 + 'IGNORABLE_LOG_EVENT', // 28 + 'ROWS_QUERY_LOG_EVENT', // 29 + 'WRITE_ROWS_EVENT_V2', // 30 + 'UPDATE_ROWS_EVENT_V2', // 31 + 'DELETE_ROWS_EVENT_V2', // 32 + 'GTID_LOG_EVENT', // 33 + 'ANONYMOUS_GTID_LOG_EVENT', // 34 + 'PREVIOUS_GTIDS_LOG_EVENT', // 35 + 'TRANSACTION_CONTEXT_EVENT', // 36 + 'VIEW_CHANGE_EVENT', // 37 + 'XA_PREPARE_LOG_EVENT', // 38 + 'PARTIAL_UPDATE_ROWS_EVENT', // 39 + 'TRANSACTION_PAYLOAD_EVENT', // 40 + 'HEARTBEAT_LOG_EVENT_V2', // 41 + 'GTID_TAGGED_LOG_EVENT' // 42 ]; const EventClass = { @@ -48,6 +56,8 @@ const EventClass = { FORMAT_DESCRIPTION_EVENT: events.Format, XID_EVENT: events.Xid, GTID_LOG_EVENT: events.GtidLog, + HEARTBEAT_LOG_EVENT: events.Heartbeat, + HEARTBEAT_LOG_EVENT_V2: events.Heartbeat_V2, TABLE_MAP_EVENT: events.TableMap, DELETE_ROWS_EVENT_V1: rowsEvents.DeleteRows, diff --git a/types/index.d.ts b/types/index.d.ts index f5a936a..9db762a 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -111,6 +111,15 @@ export type BaseBinLogEvent = { useChecksum: boolean; }; +export type BinLogHeartbeatEvent = BaseBinLogEvent & { + binlogName: string; +}; + +export type BinLogHeartbeatEvent_V2 = BaseBinLogEvent & { + binlogName: string; + position: string; +}; + export type BinLogRotationEvent = BaseBinLogEvent & { binlogName: string; position: number; @@ -170,6 +179,8 @@ export type BinLogQueryEvent = BaseBinLogEvent & { export type BinLogEvent = | BinLogRotationEvent + | BinLogHeartbeatEvent + | BinLogHeartbeatEvent_V2 | BinLogGTIDLogEvent | BinLogXidEvent | BinLogRowEvent