agentscope-ai / agentscope-ai/agentscope
[Bug]: WakeupDispatcher strands startup backlog after one batch
- Lingua principale
- Python
- Stelle
- 31.5k
- Fork
- 3.5k
- Merge medio
- 1g 23h
- PR unite (30g)
- 95
Descrizione
### Prerequisites
- [x] I have searched the existing issues and pull requests, and this is not a duplicate.
- [x] This is a bug, not a usage question.
### Summary
`WakeupDispatcher` only drains one batch of at most 64 entries when it starts. If more than 64 durable wakeup entries accumulated while the service was down, the remaining entries stay in the queue. When no new wakeup signal is published afterward, those entries are never dispatched.
This is a startup backlog bug and is distinct from [#2227](https://github.com/agentscope-ai/agentscope/issues/2227), which covers duplicate/lost resume-trigger delivery caused by concurrent multi-instance consumers and queue-consumption semantics. This issue occurs with a single dispatcher and a correctly functioning queue.
### Evidence in the current code
- `WakeupDispatcher.__aenter__` performs one initial `_drain_and_dispatch()` after subscribing:
[`src/agentscope/app/_manager/_wakeup_dispatcher.py`](https://github.com/agentscope-ai/agentscope/blob/main/src/agentscope/app/_manager/_wakeup_dispatcher.py#L115-L131)
- `_drain_and_dispatch()` reads at most 64 entries:
[`src/agentscope/app/_manager/_wakeup_dispatcher.py`](https://github.com/agentscope-ai/agentscope/blob/main/src/agentscope/app/_manager/_wakeup_dispatcher.py#L178-L209)
- The message-bus contract says entries beyond `max_count` remain in the queue for the next call:
[`src/agentscope/app/message_bus/_base.py`](https://github.com/agentscope-ai/agentscope/blob/main/src/agentscope/app/message_bus/_base.py#L130-L155)
### Reproduction
Using the real `InMemoryMessageBus` and `WakeupDispatcher` path, I pre-populated 65 durable wakeup entries and invoked the dispatcher drain once:
```text
queued entries: 65
dispatched after the startup drain: 64
remaining entries: 1
```
The remaining entry is not dispatched unless another producer publishes a new wakeup signal. With a backlog created during downtime, there may be no such signal.
The same behavior follows directly from the current code: startup invokes the drain once, and each drain is capped at 64 entries.
### Expected behavior
After subscribing at startup, the dispatcher should continue draining batches until the durable wakeup queue is empty. A backlog of 65 or more entries should not require a new producer signal before the remaining entries are processed.
The normal signal-driven loop should keep its existing bounded batch behavior where appropriate, and the change should not alter the at-most-once queue contract.
### Impact
This can leave scheduled or externally triggered agent runs permanently stuck after a normal service restart or outage followed by a burst of wakeups. The queue still contains the entries, but the dispatcher has no polling or recovery path that will read them again.
### Proposed fix and tests
Keep the existing batch size, but make the startup recovery path drain repeatedly until a call returns fewer than the batch size (or an empty batch). Add a regression test with more than 64 pre-existing entries and assert that every entry is dispatched without publishing another signal.
I would like to take this fix myself and follow up with a focused PR linked to this issue, including the regression test and the required formatting and test results. Please review the scope and proposed direction when you have a moment; I will keep the change limited to the startup backlog behavior.
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.