Skip to content

fix(NODE-7984): compare session idle time without folding it modulo one hour - #5102

Open
tap1r wants to merge 1 commit into
mongodb:mainfrom
tap1r:fix/session-timeout-idle
Open

tap1r wants to merge 1 commit into
mongodb:mainfrom
tap1r:fix/session-timeout-idle

Conversation

@tap1r

@tap1r tap1r commented Nov 3, 2026 •

Copy link
Copy Markdown

Description

Summary of Changes

ServerSession.hasTimedOut now compares elapsed idle minutes with logicalSessionTimeoutMinutes directly. It no longer reduces that duration modulo one day and then modulo one hour.

Notes for Reviewers

The - 1 minute comparison is the existing "within one minute of expiry, do not reuse" rule. Math.round is gone so a fractional minute cannot change which side of that boundary a session falls on. 9.5 minutes against a 10 minute timeout is still not reused (9.5 > 9).

Jira: NODE-7984

What is the motivation for this change?

A pooled server session idle longer than logicalSessionTimeoutMinutes was returned to the application during part of every hour. Commands then sent an lsid the server was allowed to have expired.

For bug fixes

Current (incorrect) behavior:

Idle time is folded into 0–59 minutes. With a 30 minute timeout, a session idle for 60, 120, 180, ... minutes is reused. With the driver's mock/default 10 minute timeout, a session idle for 60 minutes is reused (0 > 9 is false).

Expected behavior:

Idle time is the elapsed minutes since lastUse. The session is not reused when that value is greater than logicalSessionTimeoutMinutes - 1.

How to reproduce:

const session = new ServerSession();
session.lastUse = processTimeMS() - 60 * 60 * 1000;
session.hasTimedOut(30); // buggy result: false. elapsed minutes are 60, and 60 > 29.

Unit coverage: test/unit/sessions.test.ts ("does not reuse a session idle for one hour when the timeout is 30 minutes").

Affected versions:

The modulo is present on main (7.x / 6.x). It does not depend on a server version or topology. The server default for logicalSessionTimeoutMinutes is 30. When the topology has not reported a timeout, the pool uses 10.

Double check the following

  • Lint is passing (npm run check:lint)
  • Self-review completed using the steps outlined here
  • PR title follows the correct format: type(NODE-xxxx)[!]: description
    • Example: feat(NODE-1234)!: rewriting everything in coffeescript
  • Changes are covered by tests
  • New TODOs have a related JIRA ticket

ServerSession.hasTimedOut reduced the elapsed idle time modulo a day and
then an hour before comparing it to logicalSessionTimeoutMinutes. A
session idle for 60 minutes was treated as idle for 0, so the pool
reused an lsid the server may already have expired. That happened again
every hour. Compare the elapsed minutes directly. The one-minute margin
(timeout - 1) is unchanged.

The pool tests that passed 30 * 60 * 1000 into hasTimedOut were passing
milliseconds to a minutes parameter, so they could not fail.
@tap1r
tap1r requested a review from a team as a code owner November 3, 2026 23:54
@tap1r tap1r changed the title fix: compare session idle time without folding it modulo one hour fix(NODE-7984): compare session idle time without folding it modulo one hour Nov 4, 2026
@PavelSafronov PavelSafronov added tracked-in-jira Ticket filed in MongoDB's Jira system External Submission PR submitted from outside the team labels Nov 6, 2026
@PavelSafronov

Copy link
Copy Markdown
Contributor

@tap1r, thank you for taking the time to create this PR! This is tracked in NODE-7984. The team is currently at capacity, so we will be reviewing it over the next few quarters as capacity allows.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

External Submission PR submitted from outside the team tracked-in-jira Ticket filed in MongoDB's Jira system

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants