Skip to content

fix: replace Flux.concat with Flux.merge to fix unicast sink re-subsc…#15

Merged
ailuckly merged 1 commit into
developfrom
feat/realtime-voice-stt-p0-p1
Apr 13, 2026
Merged

fix: replace Flux.concat with Flux.merge to fix unicast sink re-subsc…#15
ailuckly merged 1 commit into
developfrom
feat/realtime-voice-stt-p0-p1

Conversation

@ailuckly
Copy link
Copy Markdown
Owner

…ription bug

Using Flux.concat caused sttFlux.share() to be subscribed twice sequentially — after the STT subscription completed, concat would subscribe llmTtsEvents which triggered a second subscription to the unicast audioSink, causing the "sinks only allow a single Subscriber" error.

Fix: wrap sttEvents and llmTtsEvents in Flux.merge so both subscribe simultaneously before any emissions, satisfying the unicast constraint.

📌 变更内容

  • 如:新增用户登录 API
  • 如:修复登录失败时错误提示

✅ 测试验证

  • 本地运行通过
  • 自测通过
  • CI 流水线通过

PR 提交规范提醒:

  • 确保提交主题信息符合约定式提交规范 (feat/fix/docs/style/refactor/test/chore)
  • 确保代码已经通过本地测试
  • 确保没有提交敏感信息(密码、密钥等)

…ription bug

Using Flux.concat caused sttFlux.share() to be subscribed twice sequentially —
after the STT subscription completed, concat would subscribe llmTtsEvents which
triggered a second subscription to the unicast audioSink, causing the
"sinks only allow a single Subscriber" error.

Fix: wrap sttEvents and llmTtsEvents in Flux.merge so both subscribe
simultaneously before any emissions, satisfying the unicast constraint.
Copilot AI review requested due to automatic review settings April 13, 2026 13:08
@ailuckly ailuckly merged commit 500d845 into develop Apr 13, 2026
6 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts the voice-processing reactive pipeline to prevent a second subscription to the shared STT stream (and the underlying unicast audio sink) by subscribing to the STT-result stream and the downstream LLM→TTS stream concurrently.

Changes:

  • Replace the sequential Flux.concat(...) chaining between sttEvents and llmTtsEvents with Flux.merge(...) so both subscribe at the same time.
  • Remove the explicit PipelineState.PROCESSING state-change event emission from the voice pipeline flow (now only internal state.set(PROCESSING) remains).

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

Comment on lines 160 to 166
return Flux.concat(
Flux.just(new PipelineEvent.StateChange(PipelineState.LISTENING)),
sttEvents.takeUntil(r -> ((PipelineEvent.SttResult) r).isFinal()),
Flux.just(new PipelineEvent.StateChange(PipelineState.PROCESSING)),
llmTtsEvents,
Flux.merge(
sttEvents.takeUntil(r -> ((PipelineEvent.SttResult) r).isFinal()),
llmTtsEvents
),
Flux.just(new PipelineEvent.Complete())
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

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

This change removes the emission of PipelineEvent.StateChange(PipelineState.PROCESSING) in the voice pipeline. The class-level state machine comment and processTextMessage both indicate clients should receive a PROCESSING transition, and AiChatWebSocketHandler forwards StateChange events to the client as pipeline_state. Consider emitting a PROCESSING StateChange when the first final STT result is received (e.g., prepend it inside the llmTtsEvents branch so it doesn't fire immediately on subscription), so voice and text flows remain consistent.

Copilot uses AI. Check for mistakes.
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.

2 participants