Skip to content

Conversation

@anmolg1997
Copy link
Contributor

@anmolg1997 anmolg1997 commented Feb 10, 2026

Link to Issue or Description of Change

Problem:

DatabaseSessionService.append_event() creates timestamps inconsistently across dialects. create_session() uses UTC and strips timezone for SQLite/PostgreSQL, but append_event() only strips for SQLite — PostgreSQL gets a local-time naive datetime via datetime.fromtimestamp(event.timestamp).

This causes get_update_timestamp() to return wrong values when the server's local timezone differs from UTC, which breaks stale session detection.

Solution:

Two targeted fixes:

  1. append_event(): Now creates a UTC-aware datetime and strips timezone for both SQLite and PostgreSQL, matching the existing create_session() behavior.

  2. get_update_timestamp(): Instead of checking is_sqlite, now checks whether the stored datetime has timezone info. Naive datetimes (from SQLite and PostgreSQL) are interpreted as UTC. Timezone-aware datetimes (MySQL, MariaDB) are used directly. This makes the method correct regardless of dialect.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

Full session test suite passes (61 tests) including all DATABASE, SQLITE, and IN_MEMORY parametrized variants:

$ pytest tests/unittests/sessions/test_session_service.py -v
61 passed in 1.22s

The critical tests that exercise this code path: test_append_event_complete, test_session_last_update_time_updates_on_event, test_append_event_to_stale_session, and test_append_event_concurrent_stale_sessions_preserve_all_state.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @anmolg1997, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses an inconsistency in how timestamps are handled for PostgreSQL within the DatabaseSessionService, which previously led to incorrect stale session detection. By standardizing timestamp creation to UTC and refining the logic for retrieving update timestamps, the changes ensure accurate session management across various database dialects, particularly for SQLite and PostgreSQL.

Highlights

  • Consistent Timestamp Handling in append_event: The append_event method now consistently converts event timestamps to UTC and strips timezone information for both SQLite and PostgreSQL, aligning with create_session's behavior to prevent asyncpg DataError or SQLite comparison issues.
  • Improved get_update_timestamp Logic: The get_update_timestamp method was refactored to check for timezone information directly, interpreting naive datetimes (from SQLite and PostgreSQL) as UTC, thereby ensuring correctness across all database dialects regardless of the server's local timezone.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/google/adk/sessions/database_session_service.py
    • Added _DATABRICKS_DIALECT constant.
    • Modified append_event to apply timezone stripping for PostgreSQL timestamps, similar to SQLite, after converting to UTC.
  • src/google/adk/sessions/schemas/v1.py
    • Updated get_update_timestamp to determine UTC interpretation based on the presence of timezone information in the datetime object, rather than relying on an is_sqlite flag.
Activity
  • Unit tests were added or updated for the change.
  • All unit tests passed locally, including the full session test suite (61 tests) across DATABASE, SQLITE, and IN_MEMORY parametrized variants.
  • Specific critical tests exercising this code path (test_append_event_complete, test_session_last_update_time_updates_on_event, test_append_event_to_stale_session, and test_append_event_concurrent_stale_sessions_preserve_all_state) were confirmed to pass.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@adk-bot adk-bot added the services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc label Feb 10, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses an inconsistency in timestamp handling for PostgreSQL, which could lead to incorrect stale session detection. The changes ensure that timestamps are consistently handled as UTC across different database dialects.

My review focuses on the correctness and clarity of the implementation. The core logic changes in append_event and get_update_timestamp are solid and effectively fix the described issue. I've added a couple of comments for minor code quality improvements: one regarding an unused constant and another about an unused function parameter that could be cleaned up in the future.

Overall, this is a good fix for a subtle but important bug.

_MARIADB_DIALECT = "mariadb"
_MYSQL_DIALECT = "mysql"
_POSTGRESQL_DIALECT = "postgresql"
_DATABRICKS_DIALECT = "databricks"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The newly added constant _DATABRICKS_DIALECT does not appear to be used anywhere in the project. If it's not intended for immediate use in a subsequent change, it should be removed to keep the codebase clean.

# SQLite does not support timezone. SQLAlchemy returns a naive datetime
# object without timezone information. We need to convert it to UTC
# manually.
def get_update_timestamp(self, is_sqlite: bool = False) -> float:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The is_sqlite parameter is no longer used within this function's body. The new implementation correctly relies on checking self.update_time.tzinfo is None, which is more robust. To improve code quality, this parameter should be removed from the function signature. This would require updating all call sites. If modifying all call sites is outside the scope of this PR, consider adding a TODO comment to track this for future refactoring.

…ionService

Fixes two timestamp inconsistencies that cause stale session detection
failures when using PostgreSQL with asyncpg:

1. append_event() now strips timezone info for PostgreSQL (matching
   create_session() behavior). Previously, PostgreSQL got a local-time
   naive datetime via datetime.fromtimestamp(), while create_session()
   stored a UTC-based naive datetime. This mismatch caused
   get_update_timestamp() to return incorrect values when the server
   timezone differs from UTC.

2. get_update_timestamp() now uses tzinfo-awareness to decide whether
   to interpret a naive datetime as UTC, rather than checking only for
   SQLite. This correctly handles both SQLite and PostgreSQL naive
   datetimes without requiring callers to pass dialect flags.

Fixes google#4366
Related: google#1848

Co-authored-by: Cursor <cursoragent@cursor.com>
@anmolg1997 anmolg1997 force-pushed the fix/postgresql-timestamp-timezone branch from c8ce8cf to 56a3317 Compare February 10, 2026 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DatabaseSessionService fails with PostgreSQL + asyncpg: can't subtract offset-naive and offset-aware datetimes

2 participants