fix(cli): defer update notifications until model response completes#3321
Merged
tanzhenxin merged 1 commit intoQwenLM:mainfrom Apr 16, 2026
Merged
Conversation
…wenLM#3046) When a background auto-update finished while the model was streaming, the success/failure notification was inserted mid-conversation via addItem(), disrupting the user's reading flow. Introduce a "defer until idle" mechanism in setUpdateHandler(): - Accept an `isIdleRef` param that tracks whether StreamingState is Idle - Queue notifications in a `pendingNotifications` array when not idle - Expose a `flush()` method that drains the queue once idle - AppContainer keeps `isIdleRef.current` in sync with `streamingState` and calls `flush()` via a useEffect when transitioning back to Idle All four event types (update-received, update-success, update-failed, update-info) are routed through the same addItemOrDefer() helper. The third parameter defaults to `{ current: true }` for backward compatibility.
tanzhenxin
approved these changes
Apr 16, 2026
Collaborator
tanzhenxin
left a comment
There was a problem hiding this comment.
Review
Clean defer-until-idle mechanism that correctly solves the reported mid-stream notification interruption. The ref-based idle tracking avoids re-renders, and the render-body assignment + effect-based flush is correct React idiom. Test suite is thorough with 10 new cases covering deferral, flush, ordering, and cleanup.
Verdict
APPROVE — Correct, well-tested fix. Ship it.
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.
When a background auto-update finished while the model was streaming,
the success/failure notification was inserted mid-conversation via
addItem(), disrupting the user's reading flow.
Introduce a "defer until idle" mechanism in setUpdateHandler():
isIdleRefparam that tracks whether StreamingState is IdlependingNotificationsarray when not idleflush()method that drains the queue once idleisIdleRef.currentin sync withstreamingStateand calls
flush()via a useEffect when transitioning back to IdleAll four event types (update-received, update-success, update-failed,
update-info) are routed through the same addItemOrDefer() helper.
The third parameter defaults to
{ current: true }for backwardcompatibility.
TLDR
When a background auto-update completed while the model was streaming a response, the success/failure notification was inserted mid-conversation via
addItem(), visually disrupting the user's reading flow. This PR introduces a "defer until idle" mechanism that queues notifications and flushes them only after the model finishes responding.Screenshots / Video Demo
Before:
After:
Dive Deeper
The fix adds an
isIdleRefparameter tosetUpdateHandler()that tracks whetherStreamingStateisIdle. All four event types (update-received,update-success,update-failed,update-info) are routed through a unifiedaddItemOrDefer()helper:addItem()pendingNotificationsqueueAppContainercallsflush()via auseEffectto drain the queueThe third parameter defaults to
{ current: true }for backward compatibility, so existing callers are unaffected.Reviewer Test Plan
Unit tests (primary validation):
18 tests cover the core scenarios: immediate delivery when idle, deferral when streaming, flush on idle transition, multi-notification ordering, cleanup clearing the queue, and empty-queue no-ops.
Code review checklist:
addItemOrDefer()correctly checksisIdleRef.currentbefore deciding to deliver or queueflush()drainspendingNotificationsin FIFO order viashift()cleanup()removes all event listeners and clears the pending queueAppContainerkeepsisIdleRef.currentin sync withstreamingStateon every renderuseEffectonstreamingStatecallsflush()only when transitioning toIdleisIdleRef = { current: true }preserves backward compatibility for any other callersSmoke test (optional):
Normal auto-update behavior (idle delivery, no mid-stream interruption) is fully covered by unit tests. Manual E2E verification is not required.
Testing Matrix
Linked issues / bugs
Fixes #3046