Repository navigation
v2.17.1
Patch release addressing post-attachment auxiliary event connection failures, lifecycle management, error reporting, and type definitions for Firebird POST_EVENT subscriptions (attachEvent() / attachEventAsync()).
Summary of Changes
Firebird events operate over a secondary TCP connection (EventConnection) distinct from the primary database wire channel. Prior to this release, unexpected socket disconnections, wire resets, or malformed event packets occurring after successful connection establishment could leave the event manager in an ambiguous state or cause unhandled exceptions. Version 2.17.1 introduces comprehensive error reporting, state transitions, callback guards, and typed event manager interfaces.
Key Improvements
1. Post-Attachment Failure Reporting
- Event Manager
errorEvent: Unexpected socket errors, remote peer disconnects, unexpected opcodes, or malformed packet payloads occurring after attachment are reported directly through the event manager'serrorevent:db.attachEvent(function (err, evtmgr) { if (err) throw err; // Handle unexpected auxiliary connection failures: evtmgr.on('error', function (err) { console.error('Auxiliary event connection failed:', err); // Manager is now CLOSED; re-attach if desired. }); evtmgr.registerEvent(['MY_EVENT'], function (err) { if (err) throw err; }); });
- Guarded Fallback: When no
'error'listener is installed onFbEventManager, the driver forwards the error through the database connection's guarded error handler (_emitError), preventing uncaughtEventEmittererror crashes. - Primary Database Isolation: An auxiliary socket failure marks only the event manager as
CLOSED; the primary database connection remains open and functional for queries and transactions.
2. Attachment Callback Idempotency
- Fixed edge cases where pre-readiness failures could invoke the
attachEventcallback multiple times or leave async promises unresolved. The callback andattachEventAsync()promise now resolve or reject strictly once.
3. Graceful Teardown & Intentional Close Suppression
- Calling
evtmgr.close()explicitly marks the auxiliary connection for intentional teardown (_intentionalClose) and detaches callbacks before closing the socket. - Suppresses spurious socket teardown errors (e.g.
ECONNRESETduring socket shutdown) from erroneously bubbling up to the database as application-level errors during deliberate closure. - Prevents stale
op_eventpackets from re-queuing event subscription loops during teardown.
4. Wire Protocol Validation
- Added payload bounds checking (
readUInt8with length validation against the buffer) to safely catch truncated or malformed event packets and convert them to terminal errors. - Unhandled wire opcodes received on the auxiliary socket trigger a terminal error cleanly instead of halting event loop execution.
5. TypeScript Definitions
- Exported complete type interfaces in
src/types.ts:FbEventManager: typed event emitter interface withregisterEvent,unregisterEvent,close,getState, and typed listeners forpost_eventanderror.FbEventState: typed snapshot of event manager state (IDLE|SUBSCRIBED|CLOSED, registered events, event ID, connection open/closed flags).FbEventManagerCallback: callback signature forattachEvent.
- Updated
Database.attachEventandDatabase.attachEventAsyncmethod definitions.
Testing & Verification
- Added comprehensive unit tests in
test/unit/event-connection.test.tscovering:- Unexpected post-attachment socket errors and single-emission verification
- Unexpected socket close handling
- Intentional shutdown error suppression
- Unknown opcode and malformed payload handling
- Pre-ready attachment error settlement
- Fallback error routing when no manager listener is installed
- All 228 unit tests pass with 0 linting and 0 TypeScript compilation errors.
- Passed full CI matrix across Node.js 20, 22, 24, and 26 against Firebird 3, 4, 5, and 6-snapshot.
Documentation
- Updated
README.mdevent connection section with recommended listener patterns, error recovery guidance, and lifecycle descriptions.
Upgrading
Drop-in replacement for 2.17.0 with no breaking changes. Applications using attachEvent() or attachEventAsync() are recommended to add an evtmgr.on('error', ...) handler before calling registerEvent().