fix(pool): use time.monotonic() instead of time.time() for connection timestamps#13288
Open
algojogacor wants to merge 1 commit into
Open
fix(pool): use time.monotonic() instead of time.time() for connection timestamps#13288algojogacor wants to merge 1 commit into
algojogacor wants to merge 1 commit into
Conversation
… timestamps Replaced all time.time() calls in pool/base.py with time.monotonic() for connection timestamp tracking. time.monotonic() is monotonic across all platforms and provides sub-millisecond precision, resolving the Windows ~16 ms granularity issue where soft invalidation checks could fail when both timestamps were captured within the same timer quantum. Fixes: sqlalchemy#13169
zzzeek
requested changes
May 12, 2026
zzzeek
left a comment
Member
There was a problem hiding this comment.
I want to do what I propose here which is dont hardcode time functions that are used in this way:
- note that we also use
time.time()in queue.py ; modern cpython correctly uses monotonic - other places we use time() for cache invalidation: and three places in asyncpg such as
sqlalchemy/lib/sqlalchemy/testing/util.py
Lines 522 to 534 in 1e1c008
steps:
- add new library function
sqlalchemy.util.compat.highres_clock()(or whatever name, but the point is it should be named for the use case, not the implementation) - apply to pool/base.py, postgresql/asyncpg.py, util/queue.py, testing/util.py
- this will be for 2.1 and i think we should have a short changelog
- thanks!
| # the issue where time.time() could have ~16 ms granularity | ||
| # on Windows, causing comparisons like _soft_invalidate_time > | ||
| # starttime to fail when both timestamps were captured within | ||
| # the same timer quantum. |
Member
There was a problem hiding this comment.
I dont want to lose the note about how >= would eliminate the issue, but would run a theoretical risk of constant re-connects if "time" were not incrementing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Replaced all
time.time()calls inpool/base.pywithtime.monotonic()for connection record timestamp tracking. Also updated the comment block that documented the Windows precision caveat.time.time()on Windows has approximately 16 ms granularity, which can cause soft invalidation checks to fail when_soft_invalidate_timeandstarttimeare captured in the same timer quantum.time.monotonic()is monotonic by definition and provides sub-millisecond precision on all platforms, so the>comparisons between timestamps work correctly regardless of platform timer resolution.Four sites changed (all in
lib/sqlalchemy/pool/base.py):Pool._invalidate_timeassignment (line 407)_ConnectionRecord._soft_invalidate_timeassignment (line 812)get_connection(line 838)_ConnectionRecord.starttimeassignment in__connect(line 893)All comparisons are relative (timestamp vs timestamp or timestamp delta vs timeout), so switching to
time.monotonic()preserves existing behavior while fixing the precision issue.time.time()comparison that can silently fail on low-resolution clocks (e.g. Windows ~16 ms) #13169