Redis append_event stamps last_update_time with the wall clock, not the event timestamp
Les mainteneurs répondent en général sous 4 jours
@sanketpatil06 y travaille déjà.
Depuis le 28/9/2026.
Évaluation
- Difficulté
- 2/5
- Temps estimé
- 1-3 heures
- Accessibilité débutants
- 88/100
Piste de recherche
Commencez dans src/google/adk/integrations/redis/_redis_session_service.py, autour de append_event, et comparez la gestion de son horodatage avec celle des autres backends de session. Exécutez tests/unittests/sessions/test_session_service.py et examinez tests/unittests/sessions/_conformance.py pour trouver l’entrée de divergence de Redis. Le travail est terminé lorsque la session Redis et sa copie rechargée utilisent l’horodatage de l’événement et que le test de conformité passe sans l’exception Redis.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
🔴 Required Information
Describe the Bug:
RedisSessionService.append_event() sets session.last_update_time to time.time() instead of the appended event's own timestamp. The other three session backends store the event's timestamp:
| backend | what it stores |
|---|---|
InMemorySessionService |
event.timestamp (in_memory_session_service.py:357-364) |
SqliteSessionService |
event_timestamp from event.timestamp (sqlite_session_service.py:433, :515-519) |
DatabaseSessionService |
event_timestamp, reloaded into last_update_time (database_session_service.py:976-1010) |
RedisSessionService |
time.time() (_redis_session_service.py:343) |
last_update_time is not cosmetic. It is the sort key list_sessions documents as "Sessions are ordered by last update time, oldest first" (base_session_service.py:102-118), and the Redis backend sorts on (s.last_update_time, s.user_id, s.id) (_redis_session_service.py:316-318).
The repository already records this as a known divergence. tests/unittests/sessions/_conformance.py registers the redis backend with the entry test_session_last_update_time_updates_on_event, and the harness docstring states that a divergence "becomes a defect anyone can pick up, and whoever fixes the backend has to delete the entry in the same change" (_conformance.py:15-31). That is the harness's own statement of the expected behaviour, marked unfixed.
Steps to Reproduce:
- Use
RedisSessionServiceas the session backend, then create a session. - Append an
Eventwhosetimestamppredates now — produced earlier, then replayed, re-delivered or imported. ADK re-delivers the same event object to a second session reference, which is whyInMemorySessionService.append_eventdedupes on event equality (in_memory_session_service.py:344-355). - Read
session.last_update_time, or calllist_sessions.
No Redis server is required; tests/unittests/integrations/redis/_fake_redis.py is an in-process stand-in.
Expected Behavior:
session.last_update_time equals event.timestamp, and the reloaded session agrees. The contract test asserts exactly this (tests/unittests/sessions/test_session_service.py:1573-1600): it builds an event at original_update_time + 10 and asserts both the in-memory and reloaded values equal it.
Observed Behavior:
The stored value is the wall clock at append time. The contract test on main at 9625b06:
XFAIL ...test_session_last_update_time_updates_on_event[redis] - Redis stamps the session with the wall clock instead of the appended event's timestamp.
5 passed, 1 xfailed
The five passing parameters are the other backends. A regression test that pins the clock far from the event's own timestamp fails by exactly the pinned offset:
E assert 1790353307.6994162 == 1790353207.6994162 ± 1.0e-06
Deterministic consequences:
- Two sessions that received the identical event report different activity times, breaking the re-delivery semantics the in-memory backend was built around.
- A session persisted via one backend and read via another (
src/google/adk/sessions/migration/) shows the Redis session jumping forward by however long the event sat in a queue, while SQLite does not. list_sessionsordering is wrong for any event that predates its append.
Optional information
Environment Details:
- ADK Library Version:
mainat9625b06c9a1be6b9ecd85225657690ae5c0e9d3e - Desktop OS: macOS
- Python Version: 3.14 locally; CI covers 3.10 through 3.14
- LiteLLM: N/A (no model call involved)
Regression: Not recent. The line has always read time.time(); the divergence entry documents it as long-standing.
Minimal reproduction:
from unittest import mock
from google.adk.events.event import Event
from google.adk.integrations.redis._config import RedisSessionServiceConfig
from google.adk.integrations.redis._redis_session_service import RedisSessionService
import pytest
@pytest.mark.asyncio
async def test_append_event_stamps_session_with_event_timestamp(session_service):
session = await session_service.create_session(app_name="app1", user_id="u1")
event_timestamp = session.last_update_time + 10
event = Event(author="agent", invocation_id="inv1", timestamp=event_timestamp)
with mock.patch("google.adk.integrations.redis._redis_session_service.time") as clock:
clock.time.return_value = event_timestamp + 100
await session_service.append_event(session, event)
assert session.last_update_time == pytest.approx(event_timestamp, abs=1e-6)
How often: Always (100%).
Scope note
This is the last_update_time defect only. The divergences map has a second Redis entry, test_append_event_to_unknown_session_raises_session_not_found, which is a separate defect: append_event writes the session key unconditionally (:384-390), so appending to a deleted, expired or never-stored session recreates it instead of raising SessionNotFoundError. That one overlaps open PR #7140, which owns those lines, and is out of scope here.
- Langage dominant
- Python
- Étoiles
- 21.8k
- Forks
- 4.1k
- Merge moyen
- 1 j 15 h
- PR mergées (30 j)
- 5
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de google/adk-python
-
Update opentelemetry-api and opentelemetry-sdk to 1.44.0Peut-être pris @llalitkumarrr l’a pris il y a 5 jours. Ouverterequest clarification tracing
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
google/adk-python#7433 · 4 commentaires · 1 personne assignée ·
Les mainteneurs répondent en général sous 4 jours
-
CI Mypy Check flags an existing streaming_utils.py error as new because the PR run reuses the baseline's mypy cachePeut-être pris @DeanChensj l’a pris il y a 7 jours. Ouverteneeds review
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
google/adk-python#7409 · 1 commentaire · 2 personnes assignées ·
Les mainteneurs répondent en général sous 4 jours
-
A2aAgentExecutor sends the raw exception text to the A2A caller when the run failsPeut-être pris @sanketpatil06 l’a pris il y a 7 jours. Ouvertea2a request clarification
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
google/adk-python#7385 · 2 commentaires · 1 personne assignée ·
Les mainteneurs répondent en général sous 4 jours
-
Please support mermaid 12 (inbuild elk) in `adk web`Peut-être pris @sanketpatil06 l’a pris il y a 8 jours. Ouverteneeds review web
Difficulté 2/5 1-3 heures Accessibilité débutants 62/100
google/adk-python#7381 · 1 commentaire · 1 personne assignée ·
Les mainteneurs répondent en général sous 4 jours
-
[A2A] RemoteA2aAgent(use_legacy=False): extension header written to state['http_kwargs'], ignored by a2a-sdk 1.x transportsPeut-être pris @surajksharma07 l’a pris il y a 14 jours. Ouvertea2a
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
google/adk-python#7334 · 2 commentaires · 1 personne assignée ·
Les mainteneurs répondent en général sous 4 jours
Toutes les issues de google/adk-python
Issues similaires
-
area: agents area: docs good first issue
Difficulté 2/5 1-3 heures Accessibilité débutants 88/100
openapi/gknowledge#23 ·
-
get() for StrEnumPeut-être pris @FeJo5952 l’a pris aujourd’hui. Ouvertegood first issue
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
collective/icalendar#1921 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
Improvement Python Spans
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
getsentry/sentry-python#7994 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
alphagov/notifications-api#5004 ·
Les mainteneurs répondent en général sous 2 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
equinor/radix-flux#3922 ·
Les mainteneurs répondent en général sous 1 jour