agentscope-ai / agentscope-ai/agentscope

[Bug]: WakeupDispatcher strands startup backlog after one batch

Aperta
#2,514 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
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.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.