mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-05-29 21:11:07 +00:00
fix(channel): stop delta coalescing at stream boundaries
This commit is contained in:
parent
5ff9146a24
commit
cf25a582ba
@ -180,7 +180,8 @@ class ChannelManager:
|
|||||||
final_metadata = dict(first_msg.metadata or {})
|
final_metadata = dict(first_msg.metadata or {})
|
||||||
non_matching: list[OutboundMessage] = []
|
non_matching: list[OutboundMessage] = []
|
||||||
|
|
||||||
# Drain all pending _stream_delta messages for the same (channel, chat_id)
|
# Only merge consecutive deltas. As soon as we hit any other message,
|
||||||
|
# stop and hand that boundary back to the dispatcher via `pending`.
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
next_msg = self.bus.outbound.get_nowait()
|
next_msg = self.bus.outbound.get_nowait()
|
||||||
@ -201,8 +202,9 @@ class ChannelManager:
|
|||||||
# Stream ended - stop coalescing this stream
|
# Stream ended - stop coalescing this stream
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# Keep for later processing
|
# First non-matching message defines the coalescing boundary.
|
||||||
non_matching.append(next_msg)
|
non_matching.append(next_msg)
|
||||||
|
break
|
||||||
|
|
||||||
merged = OutboundMessage(
|
merged = OutboundMessage(
|
||||||
channel=first_msg.channel,
|
channel=first_msg.channel,
|
||||||
|
|||||||
@ -169,6 +169,42 @@ class TestDeltaCoalescing:
|
|||||||
# No pending
|
# No pending
|
||||||
assert len(pending) == 0
|
assert len(pending) == 0
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_coalescing_stops_at_first_non_matching_boundary(self, manager, bus):
|
||||||
|
"""Only consecutive deltas should be merged; later deltas stay queued."""
|
||||||
|
await bus.publish_outbound(OutboundMessage(
|
||||||
|
channel="mock",
|
||||||
|
chat_id="chat1",
|
||||||
|
content="Hello",
|
||||||
|
metadata={"_stream_delta": True, "_stream_id": "seg-1"},
|
||||||
|
))
|
||||||
|
await bus.publish_outbound(OutboundMessage(
|
||||||
|
channel="mock",
|
||||||
|
chat_id="chat1",
|
||||||
|
content="",
|
||||||
|
metadata={"_stream_end": True, "_stream_id": "seg-1"},
|
||||||
|
))
|
||||||
|
await bus.publish_outbound(OutboundMessage(
|
||||||
|
channel="mock",
|
||||||
|
chat_id="chat1",
|
||||||
|
content="world",
|
||||||
|
metadata={"_stream_delta": True, "_stream_id": "seg-2"},
|
||||||
|
))
|
||||||
|
|
||||||
|
first_msg = await bus.consume_outbound()
|
||||||
|
merged, pending = manager._coalesce_stream_deltas(first_msg)
|
||||||
|
|
||||||
|
assert merged.content == "Hello"
|
||||||
|
assert merged.metadata.get("_stream_end") is None
|
||||||
|
assert len(pending) == 1
|
||||||
|
assert pending[0].metadata.get("_stream_end") is True
|
||||||
|
assert pending[0].metadata.get("_stream_id") == "seg-1"
|
||||||
|
|
||||||
|
# The next stream segment must remain in queue order for later dispatch.
|
||||||
|
remaining = await bus.consume_outbound()
|
||||||
|
assert remaining.content == "world"
|
||||||
|
assert remaining.metadata.get("_stream_id") == "seg-2"
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_non_delta_message_preserved(self, manager, bus):
|
async def test_non_delta_message_preserved(self, manager, bus):
|
||||||
"""Non-delta messages should be preserved in pending list."""
|
"""Non-delta messages should be preserved in pending list."""
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user