v1.3.0
Control-plane release — the seams an application needs to host its own node protocol on NodeGateway/NodeRuntime, rather than reimplementing the registry, heartbeat watchdog and RPC correlation around them.
Additive and backward-compatible: every new wire field is omitted when empty, every new hook defaults to null, and every new option defaults to the 1.2.0 behaviour. Verified by running the omnydrive (260 tests) and omnyshell (808 tests) suites unmodified against this release.
Added
Heartbeat.payload+NodeGateway.onHeartbeat+NodeConfig.heartbeatPayload— telemetry rides the beat instead of needing a second periodic message. A payload builder that throws or stalls never costs the node its liveness.NodeNotify+NodeRuntime.notify/NodeGateway.notify/onNotify— one-way push. Previously a node could only push by callingrequest()and discarding a response it did not want.- Connection lifecycle hooks —
NodeGateway.onConnect/onDisconnect/onTimeout, andNodeEvent.node. The registry's events carry a bare descriptor and never fire at all for a socket that connects without registering. NodeGateway.retainNodes— keep a disconnected or timed-out node, marked offline, for a hub that is the system of record for a known fleet. Backed byNodeRegistry.markOfflineandNodeEventKind.disconnected.RegisteredNode.state— per-node application state. The registry constructsRegisteredNodeitself, so subclassing it to add fields never worked.NodeConfig.connect(injectable transport),pingInterval,isTerminal(a revoked key is not fixed by retrying),descriptorBuilder(re-advertise on reconnect when the node has changed).AppException,WsCloseCodes.forException,TypedConnection.onDecodeError,LoggerBase.
Fixed
- Frames sent during registration were silently dropped.
NodeGatewayranonRegisterwithout awaiting it, so anything arriving while an async handler was in flight raced an unset registration and was discarded (Heartbeat,NodeUpdate) or refused asNot registered(NodeRequest). Frames are now queued and replayed in order, and discarded if registration is rejected. - A stray binary frame could take down the gateway.
MessageCodec.decodeUTF-8-decoded aBinaryMessageoutside its guard, so arbitrary bytes escaped as a rawFormatException— pastNodeGateway'sHubException-only catch — and surfaced as an uncaught async error. - An unavailable node was reported to the peer as an auth failure. Every close-code status outside 401/403/404 fell through to
unauthorized; 502/503/504 now map tobadGateway.
Changed
MessageCodec's docs claimed third parties could register new message types. They cannot — NodeControlMessage is sealed. Application protocols ride on NodeRequest/NodeResponse and NodeNotify.
278 tests (up from 246). Full notes in CHANGELOG.md.