fix(tracker): bound per-session bookkeeping dicts with LRU eviction (#18)#32
Open
santosh2345 wants to merge 1 commit into
Open
fix(tracker): bound per-session bookkeeping dicts with LRU eviction (#18)#32santosh2345 wants to merge 1 commit into
santosh2345 wants to merge 1 commit into
Conversation
_session_turn_counters, _session_turn_states and _session_providers were plain dicts with no eviction, so a server handling many unique sessions leaked memory over long uptimes — _sweep_stale_locks() only cleaned _session_locks. Closes AltioraLabs#18. - Convert the three dicts to collections.OrderedDict. - Add config.max_tracked_sessions (default 10000; 0 disables eviction). - Add _touch_session(), called on each per-turn counter increment: it marks the session most-recently-used and evicts LRU sessions beyond the limit, dropping them from all three dicts and the lock registry in lockstep. The counter dict is the LRU authority since it is written every tracked turn. - Tests: eviction beyond limit, recency refresh, and disable-when-zero, plus the config default.
abhay-2108
requested changes
Jul 16, 2026
abhay-2108
left a comment
Collaborator
There was a problem hiding this comment.
Excellent work addressing the memory leak issue (#18). Using OrderedDict for LRU tracking and evicting state/locks in sync keeps the server footprint lightweight and safe.
One design detail to note:
Direct Tracking Path (track_async / track_sync): If a user calls track_async() or track_sync() directly (bypassing the @tracker.wrap decorator), the bookkeeping dicts _session_turn_states and _session_providers are still written to inside _track_background(), but _touch_session() is never triggered.
Suggestion: For complete safety under all usage patterns, we could also call _touch_session(session_id) inside _track_background() when these fields are written.
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.
Closes #18.
_session_turn_counters,_session_turn_states, and_session_providerswere plain dicts with no eviction policy. A server handling thousands of unique sessions grows them forever — a slow memory leak._sweep_stale_locks()only cleaned_session_locks; the other three were never bounded.Changes
collections.OrderedDict.config.max_tracked_sessions(default10000;0disables eviction / restores unbounded behaviour)._touch_session(), called right after the per-turn counter increment. It marks the session most-recently-used and evicts LRU sessions beyond the limit, dropping the evicted id from all three dicts and the_session_locksregistry in lockstep. The counter dict is the LRU authority because it is written on every tracked turn.Why touch on the counter increment
It's the single per-turn chokepoint every tracked call passes through (under the per-session lock), and its key set is a superset of the state/provider dicts — so LRU order there is authoritative and eviction stays consistent. Explicit
end_session()cleanup still pops all three as before.Tests
max_tracked_sessions=0disables eviction.Verification
pytest tests/test_tracker_advanced.py tests/test_config.py tests/test_new_features.py tests/test_production_hardening.py→ 118 passed. Full suite: 390 passed (2 pre-existing failures are unrelated missing optional deps —flask,litellm).