Repository navigation
fix: avoid unread main queue copies in default in-memory manager (0.3.x) - #1276
Merged
Merged
Conversation
kabir
marked this pull request as draft
November 3, 2026 10:58
4 tasks done
kabir
marked this pull request as ready for review
November 3, 2026 11:05
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The default InMemoryQueueManager in the legacy 0.3.x line always returns a ChildQueue from createOrTap(). MainQueue nevertheless retains a second copy of every event and acquires a separate semaphore permit. Consuming all child events does not release those permits, so event 1001 blocks with the default capacity even with fast consumers. Increasing the main capacity only moves the failure boundary.
This is a maintenance-branch fix for the behavior reproduced with 0.3.3.Final. It is not a claim about the newer main-branch event-bus implementation or the root cause of every production SSE timeout.
Change
Add a package-private dispatch-only builder mode and enable it only in InMemoryQueueManager's default factory. In this mode, MainQueue distributes events to children and invokes its hook without retaining an unused main copy or acquiring a permit for that copy. Child queues still enforce bounded backpressure.
No bookkeeping dequeue is performed, so enqueue does not falsely signal awaitQueuePollerStart(). Existing close callbacks and task-state handling remain in use. Directly built queues, explicitly added queues, custom factories, and the replicated queue manager's custom factory retain their previous behavior.
The class Javadoc documents that default-manager consumers use the returned child and that tap does not replay history. With no subscribers, the default dispatch-only main queue retains no events; later subscribers receive future events.
Tests
Five queue-only regression tests cover:
Validation:
Related: agentscope-ai/agentscope-java#2507.
Supersedes the application-level workaround proposed in agentscope-ai/agentscope-java#3941, whose enqueue-hook dequeue triggered polling-start signals prematurely. AgentScope 2.0.x would still require a released SDK fix; this PR alone does not change its published dependency.
This is #1256 @Evader-lgb rebased on the latest 0.3.x branch