Yash030 commited on
Commit
e8cb8ed
·
1 Parent(s): 1ff3463

Naveen Anna Changes

Browse files
Files changed (1) hide show
  1. src/lazy_session.py +86 -0
src/lazy_session.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from typing import Optional, Dict, Any, List, AsyncGenerator
3
+ from google.adk.sessions import DatabaseSessionService, Session
4
+ from google.genai import types
5
+ import uuid
6
+ from .utils import logger
7
+
8
+ class LazyDatabaseSessionService(DatabaseSessionService):
9
+ """
10
+ A session service that defers database insertion until the first message is added.
11
+ This prevents empty sessions from cluttering the database on page loads.
12
+ """
13
+ def __init__(self, db_url: str):
14
+ super().__init__(db_url=db_url)
15
+ # In-memory store for pending sessions: {session_id: {metadata}}
16
+ self._pending_sessions: Dict[str, Dict[str, Any]] = {}
17
+
18
+ async def create_session(self, session_id: str, user_id: str, app_name: str, **kwargs) -> Session:
19
+ """
20
+ Overrides create_session to store metadata in memory instead of DB.
21
+ """
22
+ logger.info(f"💤 Lazy Session Created (Pending): {session_id}")
23
+
24
+ # Store metadata for later
25
+ self._pending_sessions[session_id] = {
26
+ "user_id": user_id,
27
+ "app_name": app_name,
28
+ "kwargs": kwargs
29
+ }
30
+
31
+ # Return a temporary Session object (not persisted yet)
32
+ # We need to mimic what the base class returns
33
+ return Session(
34
+ session_id=session_id,
35
+ user_id=user_id,
36
+ app_name=app_name,
37
+ history=[]
38
+ )
39
+
40
+ async def get_session(self, session_id: str) -> Optional[Session]:
41
+ """
42
+ Checks pending sessions first, then falls back to DB.
43
+ """
44
+ # 1. Check pending
45
+ if session_id in self._pending_sessions:
46
+ meta = self._pending_sessions[session_id]
47
+ # Return a fresh Session object from memory metadata
48
+ return Session(
49
+ session_id=session_id,
50
+ user_id=meta["user_id"],
51
+ app_name=meta["app_name"],
52
+ history=[]
53
+ )
54
+
55
+ # 2. Check DB (Super)
56
+ return await super().get_session(session_id)
57
+
58
+ async def add_message(self, session_id: str, message: types.Content) -> None:
59
+ """
60
+ On first message, persists the session to DB before adding the message.
61
+ """
62
+ # 1. Check if this is a pending session
63
+ if session_id in self._pending_sessions:
64
+ logger.info(f"⏰ Waking up Lazy Session: {session_id}")
65
+ meta = self._pending_sessions.pop(session_id)
66
+
67
+ # Persist the session now!
68
+ # We call super().create_session to actually write to DB
69
+ await super().create_session(
70
+ session_id=session_id,
71
+ user_id=meta["user_id"],
72
+ app_name=meta["app_name"],
73
+ **meta["kwargs"]
74
+ )
75
+ logger.info(f"💾 Session {session_id} persisted to DB.")
76
+
77
+ # 2. Add the message (Super)
78
+ await super().add_message(session_id, message)
79
+
80
+ async def list_sessions(self, app_name: str = None, user_id: str = None, limit: int = 10, offset: int = 0) -> List[Session]:
81
+ """
82
+ Overrides list_sessions to EXCLUDE pending sessions.
83
+ This ensures they don't show up in the UI history list.
84
+ """
85
+ # Only return sessions that are actually in the DB
86
+ return await super().list_sessions(app_name, user_id, limit, offset)