fix(gateway): thread-safe SessionStore — protect _entries with threading.Lock#3052
Merged
fix(gateway): thread-safe SessionStore — protect _entries with threading.Lock#3052
Conversation
…ing.Lock SessionStore._entries was read and mutated without synchronisation, causing race conditions when multiple platforms (Telegram + Discord) received messages concurrently on the same gateway process. Two threads could simultaneously pass the session_key check and create duplicate sessions for the same user, splitting conversation history. - Added threading.Lock to protect all _entries / _loaded mutations - Split _ensure_loaded() into public wrapper + internal _ensure_loaded_locked() - SQLite I/O is performed outside the lock to avoid blocking during slow disk operations - _save() stays inside the lock since it reads _entries for serialization Cherry-picked from PR #3012 by Kewe63. Removed unrelated changes (delivery.py case-sensitivity, hermes_state.py schema tracking) and stripped the UTC timezone switch to keep the change focused on threading.
|
4 tasks
InB4DevOps
pushed a commit
to InB4DevOps/hermes-agent
that referenced
this pull request
Mar 25, 2026
…ing.Lock (NousResearch#3052) SessionStore._entries was read and mutated without synchronisation, causing race conditions when multiple platforms (Telegram + Discord) received messages concurrently on the same gateway process. Two threads could simultaneously pass the session_key check and create duplicate sessions for the same user, splitting conversation history. - Added threading.Lock to protect all _entries / _loaded mutations - Split _ensure_loaded() into public wrapper + internal _ensure_loaded_locked() - SQLite I/O is performed outside the lock to avoid blocking during slow disk operations - _save() stays inside the lock since it reads _entries for serialization Cherry-picked from PR NousResearch#3012 by Kewe63. Removed unrelated changes (delivery.py case-sensitivity, hermes_state.py schema tracking) and stripped the UTC timezone switch to keep the change focused on threading. Co-authored-by: Kewe63 <Kewe63@users.noreply.github.com>
outsourc-e
pushed a commit
to outsourc-e/hermes-agent
that referenced
this pull request
Mar 26, 2026
…ing.Lock (NousResearch#3052) SessionStore._entries was read and mutated without synchronisation, causing race conditions when multiple platforms (Telegram + Discord) received messages concurrently on the same gateway process. Two threads could simultaneously pass the session_key check and create duplicate sessions for the same user, splitting conversation history. - Added threading.Lock to protect all _entries / _loaded mutations - Split _ensure_loaded() into public wrapper + internal _ensure_loaded_locked() - SQLite I/O is performed outside the lock to avoid blocking during slow disk operations - _save() stays inside the lock since it reads _entries for serialization Cherry-picked from PR NousResearch#3012 by Kewe63. Removed unrelated changes (delivery.py case-sensitivity, hermes_state.py schema tracking) and stripped the UTC timezone switch to keep the change focused on threading. Co-authored-by: Kewe63 <Kewe63@users.noreply.github.com>
StreamOfRon
pushed a commit
to StreamOfRon/hermes-agent
that referenced
this pull request
Mar 29, 2026
…ing.Lock (NousResearch#3052) SessionStore._entries was read and mutated without synchronisation, causing race conditions when multiple platforms (Telegram + Discord) received messages concurrently on the same gateway process. Two threads could simultaneously pass the session_key check and create duplicate sessions for the same user, splitting conversation history. - Added threading.Lock to protect all _entries / _loaded mutations - Split _ensure_loaded() into public wrapper + internal _ensure_loaded_locked() - SQLite I/O is performed outside the lock to avoid blocking during slow disk operations - _save() stays inside the lock since it reads _entries for serialization Cherry-picked from PR NousResearch#3012 by Kewe63. Removed unrelated changes (delivery.py case-sensitivity, hermes_state.py schema tracking) and stripped the UTC timezone switch to keep the change focused on threading. Co-authored-by: Kewe63 <Kewe63@users.noreply.github.com>
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.
Summary
Salvage of PR #3012 by @Kewe63. Removed unrelated changes (delivery.py case-sensitivity fix, hermes_state.py schema tracking) and stripped the UTC timezone switch to keep the change focused on threading.
Problem
SessionStore._entrieswas read and mutated without synchronisation, causing race conditions when multiple platforms (Telegram + Discord) received messages concurrently on the same gateway process. Two threads could simultaneously pass thesession_key in self._entriescheck and create duplicate sessions for the same user, splitting conversation history.Fix
threading.Lock()to protect all_entries/_loadedmutations_ensure_loaded()into public wrapper + internal_ensure_loaded_locked()_save()stays inside the lock since it reads_entriesfor serializationTest results
All 1429 gateway tests pass. Live PTY-tested with full CLI session — session created, multi-turn conversation, clean exit, DB records verified (started_at, ended_at, end_reason, messages all correct).