-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Open
Labels
services[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc
Description
Bug: DatabaseSessionService Race Condition in Table Creation and PostgreSQL Timezone Incompatibility
🔴 Required Information
Describe the Bug:
There are two issues identified when using DatabaseSessionService with PostgreSQL (via asyncpg):
- Race Condition in
_prepare_tables: When multiple concurrent requests hit the server at startup,_prepare_tablescan return early because_db_schema_versionis set by one request, even if_tables_createdis still false and tables are not yet fully created. This leads toUndefinedTableErrorbecause the tablesessionsdoes not exist when a query is executed. - Timezone Incompatibility: The
PreciseTimestamptype usesDateTime(which is timezone-naive by default in SQLAlchemy for PostgreSQL), but the service attempts to insert timezone-aware datetimes (datetime.now(timezone.utc)).asyncpgstrictly enforces timezone correctness, leading toDataError: invalid input for query argument ... (can't subtract offset-naive and offset-aware datetimes).
Steps to Reproduce:
- Install
google-adk==1.24.1andasyncpg. - Configure
DatabaseSessionServicewith a PostgreSQL URL (postgresql+asyncpg://...). - Start a FastAPI application that uses
DatabaseSessionService. - Send concurrent requests to an endpoint that uses sessions (e.g.,
list_sessionsor creating a session) immediately upon startup.
Expected Behavior:
_prepare_tablesshould block until tables are confirmed created, regardless of_db_schema_versionbeing set.PreciseTimestampshould defineDateTime(timezone=True)to createTIMESTAMP WITH TIME ZONEcolumns in PostgreSQL, allowing storage of timezone-aware datetimes.
Observed Behavior:
sqlalchemy.dialects.postgresql.asyncpg.AsyncAdapt_asyncpg_dbapi.ProgrammingError: <class 'asyncpg.exceptions.UndefinedTableError'>: relation "sessions" does not existsqlalchemy.dialects.postgresql.asyncpg.AsyncAdapt_asyncpg_dbapi.Error: <class 'asyncpg.exceptions.DataError'>: invalid input for query argument $5: datetime.datetime(...) (can't subtract offset-naive and offset-aware datetimes)
Environment Details:
- ADK Library Version: 1.24.1
- Desktop OS: Linux
- Python Version: 3.14.2
Model Information:
- Are you using LiteLLM: N/A
- Which model is being used: N/A
🟡 Optional Information
Regression:
Unknown.
Logs:
sqlalchemy.dialects.postgresql.asyncpg.AsyncAdapt_asyncpg_dbapi.ProgrammingError: <class 'asyncpg.exceptions.UndefinedTableError'>: relation "sessions" does not exist
...
sqlalchemy.dialects.postgresql.asyncpg.AsyncAdapt_asyncpg_dbapi.Error: <class 'asyncpg.exceptions.DataError'>: invalid input for query argument $5: datetime.datetime(2026, 2, 10, 21, 55, 5... (can't subtract offset-naive and offset-aware datetimes)
Additional Context:
We have patched the library locally to fix these issues.
Proposed Fix:
In google/adk/sessions/database_session_service.py:
async with self._db_schema_lock:
# Double-check after acquiring the lock
if self._db_schema_version is None: # CHANGED: Only check if None
try:
async with self.db_engine.connect() as conn:
self._db_schema_version = await conn.run_sync(
_schema_check_utils.get_db_schema_version_from_connection
)
except Exception as e:
logger.error("Failed to inspect database tables: %s", e)
raise
# Check if tables are created and create them if not
if self._tables_created:
return
# ... rest of the function ...In google/adk/sessions/schemas/shared.py:
class PreciseTimestamp(TypeDecorator):
"""Represents a timestamp precise to the microsecond."""
impl = DateTime(timezone=True) # CHANGED: Added timezone=True
cache_ok = True
# ...Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
services[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc