Align event filtering and ordering logic

Copybara import of the project:

--
d01a8fd5f079bc4fca9e4b71796dbe65312ce9ff by Leo Yongsul Kim <ystory84@gmail.com>:

fix(DatabaseSessionService): Align event filtering and ordering logic

This commit addresses inconsistencies in how DatabaseSessionService
handles config.after_timestamp and config.num_recent_events
parameters, aligning its behavior with InMemorySessionService and
VertexAiSessionService.

Key changes:
- Made after_timestamp filtering inclusive
- Corrected num_recent_events behavior to fetch the N most recent events
- Refined timezone handling for after_timestamp
- Updated the unit test test_get_session_with_config to includeSessionServiceType.DATABASE, allowing verification of these fixes.

Fixes #911

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/915 from ystory:fix/database-session-timestamp-recency 5cc8cf5f5a5c0cb3e87f6ab178a5725d3f696c88
PiperOrigin-RevId: 763874840
This commit is contained in:
Yongsul Kim 2025-05-27 11:21:15 -07:00 committed by Copybara-Service
parent 19ca61d241
commit c024ac5762
2 changed files with 5 additions and 8 deletions

View File

@ -13,7 +13,6 @@
# limitations under the License. # limitations under the License.
import copy import copy
from datetime import datetime from datetime import datetime
from datetime import timezone
import json import json
import logging import logging
from typing import Any from typing import Any
@ -371,10 +370,8 @@ class DatabaseSessionService(BaseSessionService):
return None return None
if config and config.after_timestamp: if config and config.after_timestamp:
after_dt = datetime.fromtimestamp( after_dt = datetime.fromtimestamp(config.after_timestamp)
config.after_timestamp, tz=timezone.utc timestamp_filter = StorageEvent.timestamp >= after_dt
)
timestamp_filter = StorageEvent.timestamp > after_dt
else: else:
timestamp_filter = True timestamp_filter = True
@ -382,7 +379,7 @@ class DatabaseSessionService(BaseSessionService):
session_factory.query(StorageEvent) session_factory.query(StorageEvent)
.filter(StorageEvent.session_id == storage_session.id) .filter(StorageEvent.session_id == storage_session.id)
.filter(timestamp_filter) .filter(timestamp_filter)
.order_by(StorageEvent.timestamp.asc()) .order_by(StorageEvent.timestamp.desc())
.limit( .limit(
config.num_recent_events config.num_recent_events
if config and config.num_recent_events if config and config.num_recent_events
@ -429,7 +426,7 @@ class DatabaseSessionService(BaseSessionService):
error_message=e.error_message, error_message=e.error_message,
interrupted=e.interrupted, interrupted=e.interrupted,
) )
for e in storage_events for e in reversed(storage_events)
] ]
return session return session

View File

@ -315,7 +315,7 @@ async def test_append_event_complete(service_type):
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize('service_type', [SessionServiceType.IN_MEMORY]) @pytest.mark.parametrize('service_type', [SessionServiceType.IN_MEMORY, SessionServiceType.DATABASE])
async def test_get_session_with_config(service_type): async def test_get_session_with_config(service_type):
session_service = get_session_service(service_type) session_service = get_session_service(service_type)
app_name = 'my_app' app_name = 'my_app'