Skip to content

Commit 11005e5

Browse files
fix: reload persisted sessions into memory at startup (#176)
After a server restart, session_exists() returns False for sessions that are persisted on disk, causing 404 errors on the REST endpoints. Instead of checking disk on every request (which opens an abuse vector), this loads all persisted sessions into memory once during application startup. session_exists() stays a fast memory-only check. - Added get_persisted_session_ids() to sessionmanager.py - Added reload_persisted_sessions() to memory.py - Called reload at startup in main.py lifespan handler Fixes #175 Co-authored-by: Bervianto Leo Pratama <bervianto.leo@gmail.com>
1 parent 5315d1c commit 11005e5

3 files changed

Lines changed: 33 additions & 2 deletions

File tree

chatbot-core/api/main.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from fastapi.middleware.cors import CORSMiddleware
99
from api.routes import chatbot
1010
from api.config.loader import CONFIG
11-
from api.services.memory import cleanup_expired_sessions
11+
from api.services.memory import cleanup_expired_sessions, reload_persisted_sessions
1212
from utils import LoggerFactory
1313
from pydantic import BaseModel
1414

@@ -37,6 +37,9 @@ async def lifespan(app_instance: FastAPI): # pylint: disable=unused-argument
3737
"""
3838
Manages the application lifecycle, starting background tasks on startup.
3939
"""
40+
loaded = reload_persisted_sessions()
41+
logger.info("Restored %s persisted session(s) from disk", loaded)
42+
4043
# Startup: Create the cleanup task
4144
cleanup_task = asyncio.create_task(periodic_session_cleanup())
4245
logger.info("Application startup complete, background tasks initialized")

chatbot-core/api/services/memory.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
delete_session_file,
1414
load_session,
1515
session_exists_in_json,
16-
append_message
16+
append_message,
17+
get_persisted_session_ids
1718
)
1819
# sessionId --> {"memory": ConversationBufferMemory, "last_accessed": datetime}
1920

@@ -139,6 +140,24 @@ def reset_sessions():
139140
with _lock:
140141
_sessions.clear()
141142

143+
144+
def reload_persisted_sessions() -> int:
145+
"""
146+
Load all persisted sessions from disk into memory.
147+
Called once at application startup so that session_exists()
148+
can remain a fast, memory-only check.
149+
150+
Returns:
151+
int: The number of sessions restored.
152+
"""
153+
session_ids = get_persisted_session_ids()
154+
loaded = 0
155+
for session_id in session_ids:
156+
if get_session(session_id) is not None:
157+
loaded += 1
158+
return loaded
159+
160+
142161
def get_last_accessed(session_id: str) -> Optional[datetime]:
143162
"""
144163
Get the last accessed timestamp for a given session.

chatbot-core/api/services/sessionmanager.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,12 @@ def delete_session_file(session_id: str) -> bool:
9393
Public function to delete a session's JSON file.
9494
"""
9595
return _delete_session(session_id)
96+
97+
98+
def get_persisted_session_ids() -> set:
99+
"""Return all session IDs that have persisted JSON files on disk."""
100+
return {
101+
filename[:-5]
102+
for filename in os.listdir(_SESSION_DIRECTORY)
103+
if filename.endswith(".json")
104+
}

0 commit comments

Comments
 (0)