Redis append_event stamps last_update_time with the wall clock, not the event timestamp
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 88/100
Direzione di ricerca
Inizia in src/google/adk/integrations/redis/_redis_session_service.py, intorno a append_event, e confronta la gestione del timestamp con quella degli altri backend di sessione. Esegui tests/unittests/sessions/test_session_service.py ed esamina tests/unittests/sessions/_conformance.py per la voce relativa alla divergenza di Redis. Il lavoro è completato quando la sessione Redis e la sua copia ricaricata utilizzano il timestamp dell’evento e il test di conformità passa senza l’eccezione Redis.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
🔴 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.
- Lingua principale
- Python
- Stelle
- 21.6k
- Fork
- 4k
- Merge medio
- 8h 5m
- PR unite (30g)
- 6
Preparare l'ambiente
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di google/adk-python
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
google/adk-python#7298 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
google/adk-python#7289 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
google/adk-python#7282 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
core needs review
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
google/adk-python#7266 · 2 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
mcp
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
google/adk-python#7265 · 2 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di google/adk-python
Issue simili
-
needs triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
openvinotoolkit/openvino_notebooks#3665 ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
I maintainer di solito rispondono entro 1 giorno
-
docs
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
I maintainer di solito rispondono entro 1 giorno
-
benchmark-gap
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno