Hacktoberfest 2026: as issues que os mantenedores marcaram para outubro, abertas e boas para iniciantes. Ver issues do Hacktoberfest

Redis append_event stamps last_update_time with the wall clock, not the event timestamp

Aberta Para iniciantes
#7,292 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
2/5
Tempo estimado
1-3 horas
Facilidade para iniciantes
88/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
python, redis

Direção de pesquisa

Comece em src/google/adk/integrations/redis/_redis_session_service.py, nas proximidades de append_event, e compare o tratamento do timestamp com o dos outros backends de sessão. Execute tests/unittests/sessions/test_session_service.py e inspecione tests/unittests/sessions/_conformance.py em busca da entrada de divergência do Redis. Está concluído quando a sessão Redis e sua cópia recarregada usarem o timestamp do evento e o teste de conformidade passar sem a exceção do Redis.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

🔴 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:

  1. Use RedisSessionService as the session backend, then create a session.
  2. Append an Event whose timestamp predates now — produced earlier, then replayed, re-delivered or imported. ADK re-delivers the same event object to a second session reference, which is why InMemorySessionService.append_event dedupes on event equality (in_memory_session_service.py:344-355).
  3. Read session.last_update_time, or call list_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_sessions ordering is wrong for any event that predates its append.

Optional information

Environment Details:

  • ADK Library Version: main at 9625b06c9a1be6b9ecd85225657690ae5c0e9d3e
  • 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.

Linguagem predominante
Python
Estrelas
21.6k
Forks
4k
Merge médio
12h 6min
PRs com merge (30d)
4

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de google/adk-python

Todas as issues de google/adk-python

Issues semelhantes

Mais issues de Python

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.