Skip to content

fix: batch audio processing bugs in listener2#2150

Merged
yujonglee merged 1 commit intomainfrom
devin/1764935810-fix-listener2-batch-bugs
Dec 6, 2025
Merged

fix: batch audio processing bugs in listener2#2150
yujonglee merged 1 commit intomainfrom
devin/1764935810-fix-listener2-batch-bugs

Conversation

@yujonglee
Copy link
Contributor

@yujonglee yujonglee commented Dec 5, 2025

Summary

Fixes several bugs in the batch audio processing pipeline for listener2, identified through code review with Claude CLI.

Key changes:

  1. Fix check-then-act race condition (general.ts): Call handleBatchStarted synchronously at the start of runBatch instead of clearBatchSession, preventing two concurrent calls from both passing the mode check.

  2. Fix message ordering race (batch.rs): Compute percentage directly in the streaming task and pass it with StreamResponse instead of sending a separate StreamAudioDuration message. This eliminates the race where StreamResponse could arrive before StreamAudioDuration, causing 0% progress.

  3. Increase timeout from 5s to 30s (batch.rs): The 5-second timeout was too aggressive for large audio files with gaps between transcription chunks.

  4. Fix silent message send failures (batch.rs): Log errors when send_message fails instead of silently ignoring with let _ =.

  5. Preserve original error info (ext.rs): Use |e| instead of |_| in map_err calls to include actual error details.

  6. Add UI feedback for unsupported provider (useRunBatch.ts): Throw an error instead of silently returning with console.error.

Review & Testing Checklist for Human

  • Verify state transition change: The change from clearBatchSession to handleBatchStarted in general.ts:336 - confirm this correctly prevents the race condition without breaking expected state flow
  • Test batch transcription end-to-end: Upload an audio file and verify progress percentage updates correctly (the message ordering fix is a significant refactor)
  • Test with large audio files: Verify the 30s timeout is appropriate and doesn't mask actual issues
  • Test unsupported provider error handling: Verify the thrown error in useRunBatch.ts is properly caught by callers and doesn't cause unhandled rejections

Recommended test plan:

  1. Run batch transcription with a short audio file (~30s) and verify progress updates
  2. Run batch transcription with a longer audio file (~5min) to test the timeout change
  3. Try to trigger concurrent batch calls on the same session to verify the race fix

Notes

- Fix check-then-act race: Set batch state synchronously at start of runBatch
- Fix message ordering race: Compute percentage in streaming task and pass with response
- Increase timeout from 5s to 30s for large audio files
- Fix silent message send failures: Log errors when send_message fails
- Fix error handling: Preserve original error info in ext.rs instead of discarding
- Add UI feedback for unsupported provider: Throw error instead of silent console.error

Co-Authored-By: yujonglee <yujonglee.dev@gmail.com>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@netlify
Copy link

netlify bot commented Dec 5, 2025

Deploy Preview for hyprnote ready!

Name Link
🔨 Latest commit 59d5778
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote/deploys/6932ca8ba3ca9a00086d9faf
😎 Deploy Preview https://deploy-preview-2150--hyprnote.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Dec 5, 2025

Deploy Preview for hyprnote-storybook ready!

Name Link
🔨 Latest commit 59d5778
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote-storybook/deploys/6932ca8bf8cbe8000808d491
😎 Deploy Preview https://deploy-preview-2150--hyprnote-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 5, 2025

📝 Walkthrough

Walkthrough

The PR modifies batch processing error handling and state management across the desktop application and listener plugin. Changes include replacing fallback error paths with thrown exceptions, updating batch state management calls, redesigning the StreamResponse message structure to include precomputed percentage values, and increasing timeout thresholds.

Changes

Cohort / File(s) Summary
Error Handling Improvements
apps/desktop/src/hooks/useRunBatch.ts, plugins/listener2/src/ext.rs
Replaced silent error fallbacks and generic error mapping with exception throwing and granular error messages that indicate specific failure contexts (BatchStarted, BatchResponse).
Batch State Management
apps/desktop/src/store/zustand/listener/general.ts
Changed batch start path to call handleBatchStarted(sessionId) instead of clearBatchSession(sessionId) for marking batch state transitions.
Batch Message & Processing Pipeline
plugins/listener2/src/batch.rs
Redesigned BatchMsg::StreamResponse to carry structured { response, percentage } payload; removed StreamAudioDuration variant and audio_duration_secs field from BatchState. Extended process_batch_stream signature to accept audio_duration_secs parameter. Added compute_percentage helper to calculate progress on-the-fly. Increased BATCH_STREAM_TIMEOUT_SECS from 5 to 30. Enhanced message-sending error handling with logging instead of silent failures.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Areas requiring extra attention:

  • general.ts: Verify the semantic correctness of switching from clearBatchSession to handleBatchStarted in the start path and confirm the cleanup path behavior is still appropriate.
  • batch.rs: Trace the percentage computation logic and confirm audio_duration_secs propagation through process_batch_stream and its call sites; validate that precomputed percentage values replace transcript-end-based calculations correctly.
  • Cross-file dependencies: Ensure the BatchMsg struct changes in batch.rs align with message handlers and emission calls throughout the codebase.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: batch audio processing bugs in listener2' clearly and specifically summarizes the main change: fixing multiple bugs in the batch audio processing pipeline for the listener2 plugin.
Description check ✅ Passed The description is directly related to the changeset, providing detailed explanations of six specific bug fixes with clear references to affected files and the rationale for each change.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/1764935810-fix-listener2-batch-bugs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/desktop/src/store/zustand/listener/general.ts (1)

330-337: Early handleBatchStarted is good for race-avoidance; ensure double-call is safe

Marking the batch as started before wiring the listener/issuing runBatch helps avoid a race where a second runBatch could start while the first is still initializing. However, handleBatchStarted is now invoked both here (Line 336) and again on the "batchStarted" event (Lines 360–362), so it may be called twice for the same sessionId.

Please make sure handleBatchStarted is idempotent (or guard the event-path call when state already reflects a started batch) so repeated invocations don’t regress percentage/progress state or counters.

Also applies to: 360-363

plugins/listener2/src/ext.rs (1)

121-129: Event emission now fails gracefully instead of panicking; consider aligning AM path

Mapping BatchStarted / BatchResponse .emit(&app) failures to crate::Error::BatchStartFailed(...) (Lines 121–129, 142–152, 158–166, 180–189) is a solid improvement over unwrap(): batch runs for Deepgram/Soniox will now surface structured errors instead of crashing the plugin on event-delivery issues.

One follow-up you may want (for consistency and robustness):

  • The AM provider path still calls .emit(&app).unwrap() for BatchStarted. If emitting that event can fail in practice, it would be safer to apply the same .map_err(...)? pattern there so all providers share the same failure semantics.

Functionally this change looks good as-is; the above is mostly about consistency across providers.

Also applies to: 142-152, 158-166, 180-189

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 06d7dd5 and 59d5778.

📒 Files selected for processing (4)
  • apps/desktop/src/hooks/useRunBatch.ts (1 hunks)
  • apps/desktop/src/store/zustand/listener/general.ts (1 hunks)
  • plugins/listener2/src/batch.rs (8 hunks)
  • plugins/listener2/src/ext.rs (4 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Agent implementations should use TypeScript and follow the established architectural patterns defined in the agent framework
Agent communication should use defined message protocols and interfaces

Files:

  • apps/desktop/src/store/zustand/listener/general.ts
  • apps/desktop/src/hooks/useRunBatch.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid creating a bunch of types/interfaces if they are not shared. Especially for function props, just inline them instead.
Never do manual state management for form/mutation. Use useForm (from tanstack-form) and useQuery/useMutation (from tanstack-query) instead for 99% of cases. Avoid patterns like setError.
If there are many classNames with conditional logic, use cn (import from @hypr/utils). It is similar to clsx. Always pass an array and split by logical grouping.
Use motion/react instead of framer-motion.

Files:

  • apps/desktop/src/store/zustand/listener/general.ts
  • apps/desktop/src/hooks/useRunBatch.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Redirect rules - hyprnote
  • GitHub Check: Header rules - hyprnote
  • GitHub Check: Pages changed - hyprnote
  • GitHub Check: desktop_ci (macos, depot-macos-14)
  • GitHub Check: desktop_ci (linux, depot-ubuntu-22.04-8)
  • GitHub Check: desktop_ci (linux, depot-ubuntu-24.04-8)
  • GitHub Check: fmt
  • GitHub Check: Devin
🔇 Additional comments (2)
plugins/listener2/src/batch.rs (1)

12-24: Streamed batch responses now carry a precomputed 0–1 progress ratio; verify consumer expectations

The new flow looks coherent:

  • audio_duration_secs is derived once from frame_count / sample_rate, with sane 0.0 fallback for invalid metadata (Lines 238–245).
  • process_batch_stream computes percentage = compute_percentage(&response, audio_duration_secs) and clamps it to [0.0, 1.0], returning 0.0 when the transcript end can’t be determined (Lines 336–342, 377–383).
  • BatchMsg::StreamResponse carries { response: Box<StreamResponse>, percentage: f64 }, and BatchState::emit_streamed_response emits this via BatchResponseStreamed (Lines 16–24, 47–59, 126–139).
  • All send_message calls are now wrapped with error logging, and a timeout of 30 seconds is used per response (Lines 12, 305–371), which is a safer, more debuggable behavior.

Two things to double-check:

  1. Consumer semantics of percentage – It is a normalized fraction in [0.0, 1.0], but the field name reads like “percentage”. Please confirm downstream UI/state (e.g., handleBatchResponseStreamed) expects a 0–1 ratio and doesn’t multiply again or assume 0–100.
  2. Emission frequency – Because BatchActor::handle only calls emit_streamed_response when is_final is true (Lines 132–139), you will only get a single BatchResponseStreamed emission per batch. If callers expect incremental progress updates on intermediate transcripts, this is_final gate would need to be relaxed.

If both are intended, the implementation here looks solid.

Also applies to: 47-59, 126-139, 238-245, 287-375, 377-383

apps/desktop/src/hooks/useRunBatch.ts (1)

46-49: Switch from silent fallback to thrown error improves visibility; ensure callers handle the rejection

Throwing an Error when provider is null (Lines 63–67) is a good change compared to silently returning: unsupported batch providers will now surface clearly to the caller.

Please confirm that all callsites of this hook either:

  • await the returned promise inside a try/catch, or
  • attach a .catch(...)

so this new failure mode doesn’t become an unhandled promise rejection in the UI.

Also applies to: 51-67

@yujonglee yujonglee merged commit e73e4fb into main Dec 6, 2025
16 of 17 checks passed
@yujonglee yujonglee deleted the devin/1764935810-fix-listener2-batch-bugs branch December 6, 2025 01:17
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.

1 participant