Skip to content

fix(connection): snapshot Date in heartbeat handler and flush queue on recovery#16203

Merged
vkarpov15 merged 2 commits into
Automattic:masterfrom
andreialecu:fix/gh-16183-heartbeat-buffered-ops
Apr 1, 2026
Merged

fix(connection): snapshot Date in heartbeat handler and flush queue on recovery#16203
vkarpov15 merged 2 commits into
Automattic:masterfrom
andreialecu:fix/gh-16183-heartbeat-buffered-ops

Conversation

@andreialecu
Copy link
Copy Markdown
Contributor

Summary

Fixes #16183. Two related bugs in the heartbeat staleness check:

  • Missing Date snapshot: drivers/node-mongodb-native/connection.js used the global Date.now() in the serverHeartbeatSucceeded handler instead of a snapshotted copy (like lib/connection.js already does). When test frameworks fake globalThis.Date, _lastHeartbeatAt gets a fake timestamp while the readyState getter uses the real Date.now(), causing false staleness detection.

  • No recovery path for buffered operations: When a stale heartbeat causes readyState to report disconnected, operations buffer into _queue. When the next heartbeat refreshes _lastHeartbeatAt, readyState returns connected again, but the queue is never flushed because _readyState never actually changed — so no state change event fires and onOpen() is never called. This extracts _flushQueue() from onOpen() and calls it from the heartbeat handler when the connection is no longer stale.

Test plan

  • Added test: heartbeat handler uses snapshotted Date, not affected by faked globalThis.Date
  • Added test: buffered operations flush when heartbeat refreshes stale connection
  • Added test: child db (useDb()) queues also flush on heartbeat recovery
  • Existing connection pool sharing tests all pass
  • ESLint passes on changed files

…n recovery (Automatticgh-16183)

The heartbeat handler in drivers/node-mongodb-native/connection.js used the
global Date.now() instead of a snapshotted copy, causing fake timers to write
incorrect timestamps to _lastHeartbeatAt. Additionally, when a stale heartbeat
caused readyState to report disconnected, buffered operations were never
flushed because _readyState never actually changed — so no state change event
fired. This extracts _flushQueue() from onOpen() and calls it from the
heartbeat handler when the connection is no longer stale.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes connection staleness false-positives and ensures buffered operations resume after a stale-heartbeat “recovery”, aligning the node-mongodb-native driver connection behavior with the core Connection implementation and preventing hangs like startSession() timing out under Date-mocking test frameworks.

Changes:

  • Snapshot globalThis.Date in lib/drivers/node-mongodb-native/connection.js so heartbeat timestamps use the real clock even if globalThis.Date is later faked.
  • Flush buffered connection operations from the heartbeat success handler when a previously-stale connection becomes non-stale again (including useDb() child connections).
  • Extract queue-flushing into Connection.prototype._flushQueue() and add tests covering the fixed scenarios.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
test/connection.test.js Adds regression tests for Date snapshotting and queue flushing on heartbeat recovery (including child dbs).
lib/drivers/node-mongodb-native/connection.js Snapshots Date and flushes _queue / child queues on serverHeartbeatSucceeded when the connection is no longer stale.
lib/connection.js Refactors onOpen() to call a new _flushQueue() helper method.

Comment thread test/connection.test.js Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@vkarpov15 vkarpov15 added this to the 9.4 milestone Apr 1, 2026
Copy link
Copy Markdown
Collaborator

@vkarpov15 vkarpov15 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks 👍

@vkarpov15 vkarpov15 merged commit 5ae20fa into Automattic:master Apr 1, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

startSession() / buffered operations hang

3 participants