5.4 Release Notes
Patch Releases
All patch release notes for 5.4.x are available on the releases page.
Subscriptions
Resuming a Subscription From a Checked Position
A subscribe request can now carry the databaseGeneration its position came from. Harper then checks the position before and during the replay, and refuses one whose history was replaced (DatabaseGenerationChangedError, status code 409) or pruned (ResumeHistoryUnavailableError, status code 410) instead of replaying what is left. The subscription's resumeVerified promise resolves true once the replay is complete and checked. Requests without the field behave as before, and the check applies to RocksDB databases only. See Resuming from a position.
Durable MQTT Sessions No Longer Replay Short
A durable MQTT session now resumes through the same checked replay. When a reconnect's saved position names history that audit retention has removed, Harper deletes the session and reports sessionPresent: false (or, if the problem appears after CONNACK, sends an MQTT v5 DISCONNECT with reason code 0x83 and closes the connection) instead of delivering a partial catch-up. A position saved before a restore or copy, or on another cluster node, resumes best-effort, as before. A quiet topic's position is kept current, so retention on other tables does not reset it, and positions no longer skip unacknowledged messages that share a transaction. Resubscribing to a topic the session already holds continues from its saved position, and QoS 0 subscriptions are kept with the session and resume live. Each connection's Last Will is kept separately, so a connection that is taken over publishes its own will, never the newer connection's. See Durable Sessions.
Component Deploys
Certifying a Release in a Canary Worker
A deploy_component with restart: true or restart: "rolling" now checks its release before rolling it out. The first worker started on the release, the canary, is held out of traffic until it reports whether the deployed component loaded, and the rollout goes on only if it did. Each later replacement is checked the same way. When the node that received the deploy rejects the release, the deploy fails with 400. The release it replaced is made live again, or, with nothing to go back to, the component fails closed on that node. A new certification field in the response reports the outcome, and says when a restarting deploy went out unchecked (uncertified or unavailable, as for a package: file:<dir> deploy). With "rolling", each other node then certifies the release with a canary of its own, and a node that rejects it fails the deploy's job, not the deploy: poll its restartJobId with get_job for the outcome. A node running a version before 5.4.0 activates without a canary. A deploy that restarts nothing is not test-loaded. If its release throws when it loads, get_status reports the failure. See Certifying a release in a canary worker.