fix memory leak in InMemorySessionBackend, should still not be used in prod, implement your own session backend with persistance

Commit 0c21f43 · patx · 2025-12-03T20:34:50-05:00

Changeset
0c21f431256286e621a3ce43aac0b5a68ca14e55
Parents
221685ff053f66a644ac9ca32fa1a2724d481f43

View source at this commit

Comments

No comments yet.

Log in to comment

Diff

diff --git a/micropie.py b/micropie.py
index 8185acc..441a2fa 100644
--- a/micropie.py
+++ b/micropie.py
@@ -72,19 +72,29 @@ class InMemorySessionBackend(SessionBackend):
         self.sessions: Dict[str, Dict[str, Any]] = {}
         self.last_access: Dict[str, float] = {}
 
+    def _cleanup(self):
+        """Remove expired sessions based on SESSION_TIMEOUT."""
+        now = time.time()
+        expired = [
+            sid for sid, ts in self.last_access.items()
+            if now - ts >= SESSION_TIMEOUT
+        ]
+        for sid in expired:
+            self.sessions.pop(sid, None)
+            self.last_access.pop(sid, None)
+
     async def load(self, session_id: str) -> Dict[str, Any]:
+        self._cleanup()
         now = time.time()
-        if session_id in self.sessions and (now - self.last_access.get(session_id, now)) < SESSION_TIMEOUT:
+        if session_id in self.sessions:
             self.last_access[session_id] = now
             return self.sessions[session_id]
         return {}
 
     async def save(self, session_id: str, data: Dict[str, Any], timeout: int) -> None:
-        """
-        If `data` is empty, treat this as a logout and remove the session.
-        Otherwise, upsert the session and update last_access.
-        """
+        self._cleanup()
         if not data:
+            # treat empty as delete
             self.sessions.pop(session_id, None)
             self.last_access.pop(session_id, None)
         else: