Channels outbox: follow-ups from the #7105 review (lease renewal, clock skew, batch blocking, failed-start notice)

Aperta
#7,114 2 commenti 1 reazione 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
45/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
postgresql, python, redis

Direzione di ricerca

Start with api/oss/src/tasks/asyncio/channels/outbox.py and the referenced DAO, adapter, and inbox methods; read the four review findings and the #7105 claim implementation first. Check the existing tests for outbox claiming, retries, batch processing, and failed-start notices. Done means the four races and timing cases are handled without duplicate posts or unfenced receipt writes, with tests covering each behavior.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

🤖 The AI agent says:

Follow-ups from the adversarial review of #7105 (the channels outbox delivery claim). #7105 fixed the findings that cause duplicate or lost replies in normal operation. These four are left for later. Line numbers refer to fix/channels-outbox-atomic-claim at 7ecb3a9.

1. The 60s claim lease is never renewed (review finding 3)

_CLAIM_TTL_SECONDS = 60.0 (api/oss/src/tasks/asyncio/channels/outbox.py:71). The claim is stamped once (api/oss/src/dbs/postgres/channels/dao.py:1828-1830) and never extended while the post runs. A multi-chunk post loops over chunks (api/oss/src/core/channels/adapters/slack/adapter.py:444, api/oss/src/core/channels/adapters/telegram/adapter.py:336). Each chunk can take up to the httpx timeouts, and there is no overall deadline, so a long answer on a slow platform can outlive the lease. Another worker then takes the row over and posts the whole answer again. The claim token fences the receipt write, but it cannot recall what was already posted.

Options: renew the lease between chunks (a fenced UPDATE ... SET updated_at = now()), or put a total deadline on a post that is well under the TTL.

2. The 10-minute cutoff compares the worker clock with the Redis clock (review finding 5)

_past_retry_window (outbox.py:921-928) computes the age as time.time() on the worker minus the millisecond part of the Redis stream id, which Redis stamps with its own clock. Clock skew between the worker host and Redis shifts the window: a worker clock running ahead drops fresh entries early, and one running behind replays old ones. The same comparison runs on reclaimed entries in reclaim_batch (outbox.py:901).

Options: read the Redis clock (TIME) once per reclaim pass and compare against that, or compare with the idle time that XPENDING already returns.

3. A loser's 15s wait blocks the whole batch (review finding 6)

_claim_delivery (outbox.py:735-785) polls a busy row for up to _CLAIM_WAIT_SECONDS = 15.0 (outbox.py:72) before raising. process_batch (outbox.py:948) handles entries one after another, so every later entry in the batch (up to 50, for other turns and other chats) waits behind that poll. It is rare (it needs two workers on the same row), but when it happens every reply in the batch is late.

Options: handle entries concurrently per row key, or skip the wait and leave the entry pending for the reclaim pass.

4. The failed-start notice bypasses the claim (review finding 7)

The failed-start notice, InboxDispatcher._notify_not_started (api/oss/src/tasks/asyncio/channels/inbox.py:763-800), reads the item-0 row (inbox.py:764), posts with adapter.post_message (inbox.py:785), and writes SENT (inbox.py:792) without claim_outbox_delivery. A redelivered dispatcher task, or one racing a sessions-outbox delivery on the same row, can post the notice twice or write over the other writer's receipt.

Fix: route it through the same claim, fenced transition and unknown-outcome rule that ChannelsOutboxWorker._send uses.

Lingua principale
TypeScript
Stelle
4.8k
Fork
690
Merge medio
20h 11m
PR unite (30g)
448

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di Agenta-AI/agenta

Tutte le issue di Agenta-AI/agenta

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.