Skip to content

Commit 666cebe

Browse files
GWealecopybara-github
authored andcommitted
fix: Add update_timestamp_tz property to StorageSession
This property is a compatibility alias that returns the update timestamp as a POSIX timestamp. It infers whether the database is SQLite using sqlalchemy.inspect to call get_update_timestamp correctly Close #4334 Co-authored-by: George Weale <gweale@google.com> PiperOrigin-RevId: 864595914
1 parent dd8cd27 commit 666cebe

3 files changed

Lines changed: 66 additions & 1 deletion

File tree

src/google/adk/sessions/schemas/v0.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from sqlalchemy import Boolean
3939
from sqlalchemy import ForeignKeyConstraint
4040
from sqlalchemy import func
41+
from sqlalchemy import inspect
4142
from sqlalchemy import Text
4243
from sqlalchemy.dialects import mysql
4344
from sqlalchemy.ext.mutable import MutableDict
@@ -130,6 +131,20 @@ class StorageSession(Base):
130131
def __repr__(self):
131132
return f"<StorageSession(id={self.id}, update_time={self.update_time})>"
132133

134+
@property
135+
def update_timestamp_tz(self) -> float:
136+
"""Returns the update timestamp as a POSIX timestamp.
137+
138+
This is a compatibility alias for callers that used the pre-`main` API.
139+
"""
140+
sqlalchemy_session = inspect(self).session
141+
is_sqlite = bool(
142+
sqlalchemy_session
143+
and sqlalchemy_session.bind
144+
and sqlalchemy_session.bind.dialect.name == "sqlite"
145+
)
146+
return self.get_update_timestamp(is_sqlite=is_sqlite)
147+
133148
def get_update_timestamp(self, is_sqlite: bool) -> float:
134149
"""Returns the time zone aware update timestamp."""
135150
if is_sqlite:

src/google/adk/sessions/schemas/v1.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
from datetime import datetime
2727
from datetime import timezone
2828
from typing import Any
29-
from typing import Optional
3029
import uuid
3130

3231
from sqlalchemy import ForeignKeyConstraint
3332
from sqlalchemy import func
33+
from sqlalchemy import inspect
3434
from sqlalchemy.ext.mutable import MutableDict
3535
from sqlalchemy.orm import DeclarativeBase
3636
from sqlalchemy.orm import Mapped
@@ -105,6 +105,20 @@ class StorageSession(Base):
105105
def __repr__(self):
106106
return f"<StorageSession(id={self.id}, update_time={self.update_time})>"
107107

108+
@property
109+
def update_timestamp_tz(self) -> float:
110+
"""Returns the update timestamp as a POSIX timestamp.
111+
112+
This is a compatibility alias for callers that used the pre-`main` API.
113+
"""
114+
sqlalchemy_session = inspect(self).session
115+
is_sqlite = bool(
116+
sqlalchemy_session
117+
and sqlalchemy_session.bind
118+
and sqlalchemy_session.bind.dialect.name == "sqlite"
119+
)
120+
return self.get_update_timestamp(is_sqlite=is_sqlite)
121+
108122
def get_update_timestamp(self, is_sqlite: bool) -> float:
109123
"""Returns the time zone aware update timestamp."""
110124
if is_sqlite:

tests/unittests/sessions/migration/test_migration.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,39 @@ def test_migrate_from_sqlalchemy_pickle_with_async_driver_urls(tmp_path):
245245
assert session_res.id == "async_session"
246246

247247
dest_session.close()
248+
249+
250+
def _assert_update_timestamp_tz_is_utc_timestamp(schema_module) -> None:
251+
engine = create_engine("sqlite:///:memory:")
252+
schema_module.Base.metadata.create_all(engine)
253+
SessionLocal = sessionmaker(bind=engine)
254+
255+
update_time = datetime(2026, 1, 1, 0, 0, 0)
256+
storage_session = schema_module.StorageSession(
257+
app_name="app",
258+
user_id="user",
259+
id="sid",
260+
state={},
261+
create_time=update_time,
262+
update_time=update_time,
263+
)
264+
265+
with SessionLocal() as db:
266+
db.add(storage_session)
267+
db.commit()
268+
269+
fetched = db.get(schema_module.StorageSession, ("app", "user", "sid"))
270+
assert fetched is not None
271+
assert isinstance(fetched.update_timestamp_tz, float)
272+
assert (
273+
fetched.update_timestamp_tz
274+
== update_time.replace(tzinfo=timezone.utc).timestamp()
275+
)
276+
277+
278+
def test_v1_storage_session_update_timestamp_tz() -> None:
279+
_assert_update_timestamp_tz_is_utc_timestamp(v1)
280+
281+
282+
def test_v0_storage_session_update_timestamp_tz() -> None:
283+
_assert_update_timestamp_tz_is_utc_timestamp(v0)

0 commit comments

Comments
 (0)