Skip to content

Commit

Permalink
fix(connection): avoid returning readyState = connected if connecti…
Browse files Browse the repository at this point in the history
…on state is stale

Fix #14727
  • Loading branch information
vkarpov15 committed Aug 17, 2024
1 parent ca0191c commit 06839fa
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 0 deletions.
9 changes: 9 additions & 0 deletions lib/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ Object.setPrototypeOf(Connection.prototype, EventEmitter.prototype);

Object.defineProperty(Connection.prototype, 'readyState', {
get: function() {
// If connection thinks it is connected, but we haven't received a heartbeat in 2 heartbeat intervals,
// that likely means the connection is stale (potentially due to frozen AWS Lambda container)
if (
this._readyState === STATES.connected &&
this._lastHeartbeatAt != null &&
typeof this.client?.topology?.s?.description?.heartbeatFrequencyMS === 'number' &&
Date.now() - this._lastHeartbeatAt >= this.client.topology.s.description.heartbeatFrequencyMS * 2) {
return STATES.disconnected;
}
return this._readyState;
},
set: function(val) {
Expand Down
15 changes: 15 additions & 0 deletions lib/drivers/node-mongodb-native/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ const utils = require('../../utils');
function NativeConnection() {
MongooseConnection.apply(this, arguments);
this._listening = false;
// Tracks the last time (as unix timestamp) the connection received a
// serverHeartbeatSucceeded or serverHeartbeatFailed event from the underlying MongoClient.
// If we haven't received one in a while (like due to a frozen AWS Lambda container) then
// `readyState` is likely stale.
this._lastHeartbeatAt = null;
}

/**
Expand Down Expand Up @@ -106,6 +111,7 @@ NativeConnection.prototype.useDb = function(name, options) {
_opts.noListener = options.noListener;
}
newConn.db = _this.client.db(name, _opts);
newConn._lastHeartbeatAt = _this._lastHeartbeatAt;
newConn.onOpen();
}

Expand Down Expand Up @@ -409,6 +415,12 @@ function _setClient(conn, client, options, dbName) {
}
});
}
client.on('serverHeartbeatSucceeded', () => {
conn._lastHeartbeatAt = Date.now();
});
client.on('serverHeartbeatFailed', () => {
conn._lastHeartbeatAt = Date.now();
});

if (options.monitorCommands) {
client.on('commandStarted', (data) => conn.emit('commandStarted', data));
Expand All @@ -417,6 +429,9 @@ function _setClient(conn, client, options, dbName) {
}

conn.onOpen();
if (client.topology?.s?.state === 'connected') {
conn._lastHeartbeatAt = Date.now();
}

for (const i in conn.collections) {
if (utils.object.hasOwnProperty(conn.collections, i)) {
Expand Down

0 comments on commit 06839fa

Please sign in to comment.