Skip to content

fix: drain entire queue per flush to avoid streaming tail lag#424

Merged
heyitsaamir merged 3 commits into
mainfrom
fix/drain-entire-stream-queue-per-flush
May 4, 2026
Merged

fix: drain entire queue per flush to avoid streaming tail lag#424
heyitsaamir merged 3 commits into
mainfrom
fix/drain-entire-stream-queue-per-flush

Conversation

@heyitsaamir

Copy link
Copy Markdown
Collaborator

Summary

  • Removes the 10-item batch cap in Stream.Flush() so each flush cycle drains the entire queue
  • Prevents a long streaming tail when the LLM finishes generating faster than chunks are sent to Teams
  • Port of microsoft/teams.py#384 / microsoft/teams.ts#520

Test plan

  • Existing AspNetCorePluginStreamTests pass (15/15 on both net8.0 and net10.0)
  • Build succeeds with no warnings

🤖 Generated with Claude Code

Remove the 10-item batch cap in Stream.Flush() so each cycle
processes all queued items, preventing a long streaming tail when
the LLM finishes faster than chunks are sent to Teams.

Port of microsoft/teams.py#384 / microsoft/teams.ts#520.

Co-Authored-By: Claude <[email protected]>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Removes the fixed 10-item cap in Stream.Flush() so each flush cycle drains the entire pending activity queue, reducing “tail lag” when generation outpaces outbound sending.

Changes:

  • Remove the 10-item batch limit in Flush() and drain _queue fully per flush
  • Replace the “no work done” check (i == 0) with a queue-count-based early return guard
Comments suppressed due to low confidence (1)

Libraries/Microsoft.Teams.Plugins/Microsoft.Teams.Plugins.AspNetCore/AspNetCorePlugin.Stream.cs:1

  • startCount is computed from _queue.Count, which is not a reliable indicator of whether this flush actually dequeued items in concurrent scenarios. If _queue.Count is 0 at line 138 but items are enqueued immediately after and then dequeued in the loop, startCount == 0 will still be true and the method will return early, potentially dropping/defering sends even though activities were drained and _count was incremented. Prefer tracking whether anything was actually dequeued (e.g., var dequeued = 0; increment inside the loop and if (dequeued == 0) return;), which matches the previous i == 0 behavior and avoids reliance on _queue.Count.
// Copyright (c) Microsoft Corporation. All rights reserved.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

MehakBindra
MehakBindra previously approved these changes Apr 13, 2026
heyitsaamir and others added 2 commits May 4, 2026 15:14
Fixes race condition where _queue.Count snapshot could be 0 before
the drain loop but items get enqueued and dequeued during the loop,
causing the early return to skip sending those activities.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@heyitsaamir
heyitsaamir merged commit a76a235 into main May 4, 2026
8 checks passed
@heyitsaamir
heyitsaamir deleted the fix/drain-entire-stream-queue-per-flush branch May 4, 2026 22:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants