A message that arrives between the first poll and the broker wait is delivered only after the full long-poll timeout #157

Closed
opened 2026-10-20 17:14:52 +02:00 by clawbot · 0 comments
Collaborator

HandleGetMessages in internal/handlers/api.go first calls PollMessages; if that returns nothing it calls longPoll, which only then registers with broker.Wait(sessionID). Broker.Notify (internal/broker/broker.go) wakes the channels registered at that moment and nothing else. A message queued and notified between the empty poll and the Wait wakes nobody, so the request sleeps for the whole timeout (up to 30 s) and the client sees the message on its next poll. README.md (Long-Polling) says the server responds when a message arrives, instantly via the broker. The window is the few microseconds between the two calls; not reproduced in 300 timed attempts on eceb5f2, but the order is plain in the code. relayMessages in internal/ircserver/relay.go has the same order and is bounded by its 100 ms fallback ticker.

Fix: register the wait channel before the first PollMessages, then poll; if the poll finds something, remove the channel and answer; if not, wait on the channel already registered. Nothing can then be notified unseen. The same reorder in relayMessages.

Definition of done

  1. In HandleGetMessages, the broker wait is registered before the first poll of the queue and removed on every exit path; relayMessages likewise.
  2. A test in internal/handlers that a message enqueued and notified right after the handler has registered, before its first poll, is returned at once rather than after the timeout.
  3. One reviewed PR against next.

Model: fable-5-1

`HandleGetMessages` in `internal/handlers/api.go` first calls `PollMessages`; if that returns nothing it calls `longPoll`, which only then registers with `broker.Wait(sessionID)`. `Broker.Notify` (`internal/broker/broker.go`) wakes the channels registered at that moment and nothing else. A message queued and notified between the empty poll and the `Wait` wakes nobody, so the request sleeps for the whole `timeout` (up to 30 s) and the client sees the message on its next poll. `README.md` (Long-Polling) says the server responds when a message arrives, instantly via the broker. The window is the few microseconds between the two calls; not reproduced in 300 timed attempts on `eceb5f2`, but the order is plain in the code. `relayMessages` in `internal/ircserver/relay.go` has the same order and is bounded by its 100 ms fallback ticker. Fix: register the wait channel before the first `PollMessages`, then poll; if the poll finds something, remove the channel and answer; if not, wait on the channel already registered. Nothing can then be notified unseen. The same reorder in `relayMessages`. ## Definition of done 1. In `HandleGetMessages`, the broker wait is registered before the first poll of the queue and removed on every exit path; `relayMessages` likewise. 2. A test in `internal/handlers` that a message enqueued and notified right after the handler has registered, before its first poll, is returned at once rather than after the timeout. 3. One reviewed PR against `next`. Model: fable-5-1
clawbot self-assigned this 2026-10-20 17:14:52 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/neoirc#157