Redis append_event stamps last_update_time with the wall clock, not the event timestamp
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 2/5
- Geschätzter Aufwand
- 1-3 Stunden
- Anfängerfreundlichkeit
- 88/100
Rechercherichtung
Beginne in src/google/adk/integrations/redis/_redis_session_service.py rund um append_event und vergleiche die Behandlung des Zeitstempels dort mit der der anderen Session-Backends. Führe tests/unittests/sessions/test_session_service.py aus und prüfe tests/unittests/sessions/_conformance.py auf den Eintrag zur Redis-Abweichung. Erledigt ist die Aufgabe, wenn die Redis-Session und ihre neu geladene Kopie den Event-Zeitstempel verwenden und der Conformance-Test ohne die Redis-Ausnahme erfolgreich ist.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
🔴 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.
- Vorherrschende Sprache
- Python
- Sterne
- 21.6k
- Forks
- 4k
- Ø Merge
- 6 Std. 56 Min.
- Gemergte PRs (30 T.)
- 7
Entwicklungsumgebung
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus google/adk-python
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
google/adk-python#7289 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
google/adk-python#7282 · 2 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
core needs review
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
google/adk-python#7266 · 2 Kommentare · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
mcp
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
google/adk-python#7265 · 2 Kommentare · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
RestApiTool crashes the agent run on a non-UTF-8 error response body (UnicodeDecodeError in the HTTPStatusError handler)Evtl. vergeben @llalitkumarrr hat das vor 5 Tagen übernommen. Offencore
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
google/adk-python#7206 · 2 Kommentare · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in google/adk-python
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
solana-foundation/pay-kit#341 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
nasa/python_cmr#123 ·
-
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 92/100
EleutherAI/lm-evaluation-harness#4243 ·
Maintainer antworten meist innerhalb von 1 Tag
-
area: dashboard bug perceived difficulty: 3
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
Nitjsefnie-Harness-Commons/daedalus#1179 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
cusp-ai-oss/tojax#17 ·