Skip to content

Conversation

@yujonglee
Copy link
Contributor

No description provided.

@netlify
Copy link

netlify bot commented Nov 25, 2025

Deploy Preview for hyprnote ready!

Name Link
🔨 Latest commit 2748d20
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote/deploys/69257b72d32458000865b5f0
😎 Deploy Preview https://deploy-preview-1881--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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 25, 2025

📝 Walkthrough

Walkthrough

The PR integrates ractor-based actor supervision across the desktop application and plugins. It adds workspace dependencies for ractor and ractor-supervisor, introduces a root supervisor spawned at application startup, and updates listener and local-stt plugins with InitOptions to support optional hierarchical parent supervision via ActorCell linking.

Changes

Cohort / File(s) Summary
Dependency additions
apps/desktop/src-tauri/Cargo.toml
Added workspace-based dependencies ractor and ractor-supervisor to enable actor supervision framework.
Root supervisor infrastructure
apps/desktop/src-tauri/src/lib.rs,
apps/desktop/src-tauri/src/supervisor.rs
Created new supervisor module with spawn_root_supervisor() function that configures and spawns a DynamicSupervisor with restart policies (max_restarts: 50, max_window: 60s). Root supervisor is spawned at startup and passed to plugins via InitOptions.
Listener plugin supervision
plugins/listener/src/lib.rs,
plugins/listener/src/supervisor.rs
Added supervisor module with spawn_listener_supervisor(parent) function supporting optional parent linkage. Changed SharedState from Mutex<State> to Arc<Mutex<State>>, exposed app field, added listener_supervisor and supervisor_handle fields to State, introduced InitOptions with parent_supervisor, and updated init signature to accept options.
Local-stt plugin supervision
plugins/local-stt/src/lib.rs,
plugins/local-stt/src/server/supervisor.rs
Added InitOptions with optional parent_supervisor, updated init signature to accept options, and modified spawn_stt_supervisor() to accept optional parent ActorCell and conditionally link supervisor to parent if provided.

Sequence Diagram

sequenceDiagram
    participant App as Desktop App
    participant RS as Root Supervisor
    participant LP as Listener Plugin
    participant LS as Local-STT Plugin
    
    App->>RS: spawn_root_supervisor()
    RS-->>App: SupervisorRef, Handle
    
    App->>LP: init(InitOptions{parent_supervisor})
    LP->>LP: spawn_listener_supervisor(parent)
    LP->>RS: link via ActorCell
    LP-->>App: TauriPlugin
    
    App->>LS: init(InitOptions{parent_supervisor})
    LS->>LS: spawn_stt_supervisor(parent)
    LS->>RS: link via ActorCell
    LS-->>App: TauriPlugin
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Arc<Mutex> migration in listener plugin: Verify correct usage patterns and lifetime safety; ensure no unintended synchronization overhead introduced.
  • Parent-child supervisor linkage via ActorCell: Confirm proper linking semantics and error propagation when parent is unavailable; test restart cascading.
  • Initialization ordering: Validate that root supervisor is guaranteed to be available before plugins attempt to link to it; audit InitOptions propagation pipeline.
  • Async supervisor spawning and error handling: Review error cases in spawn_root_supervisor(), spawn_listener_supervisor(), and spawn_stt_supervisor() for proper logging and graceful degradation.
  • SharedState type change impact: Check all State access patterns in listener plugin for compatibility with Arc<Mutex> constraints.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided by the author, which is insufficient to convey the purpose and scope of the changes. Add a description explaining the purpose of the root supervisor, why it was added, and how it affects the plugin initialization and supervision hierarchy.
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding a root supervisor system to the desktop application with new supervisor module and initialization flow.
✨ 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 yl-branch-57

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

@netlify
Copy link

netlify bot commented Nov 25, 2025

Deploy Preview for hyprnote-storybook ready!

Name Link
🔨 Latest commit 2748d20
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote-storybook/deploys/69257b726188ed0008703986
😎 Deploy Preview https://deploy-preview-1881--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.

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: 1

🧹 Nitpick comments (1)
plugins/listener/src/supervisor.rs (1)

11-18: Consider documenting the supervisor configuration rationale.

The listener supervisor uses max_children: 10, max_restarts: 50 while the STT supervisor uses max_children: 1, max_restarts: 100. These differences are likely intentional based on the nature of each supervisor's workload. A brief comment explaining the chosen values would help future maintainers.

📜 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 54e1f76 and 2748d20.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • apps/desktop/src-tauri/Cargo.toml (1 hunks)
  • apps/desktop/src-tauri/src/lib.rs (3 hunks)
  • apps/desktop/src-tauri/src/supervisor.rs (1 hunks)
  • plugins/listener/src/lib.rs (4 hunks)
  • plugins/listener/src/supervisor.rs (1 hunks)
  • plugins/local-stt/src/lib.rs (5 hunks)
  • plugins/local-stt/src/server/supervisor.rs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
plugins/local-stt/src/lib.rs (1)
plugins/local-stt/src/server/supervisor.rs (1)
  • spawn_stt_supervisor (28-41)
apps/desktop/src-tauri/src/lib.rs (3)
apps/desktop/src-tauri/src/supervisor.rs (1)
  • spawn_root_supervisor (12-30)
plugins/listener/src/lib.rs (1)
  • init (62-98)
plugins/local-stt/src/lib.rs (1)
  • init (57-94)
plugins/listener/src/lib.rs (1)
plugins/listener/src/supervisor.rs (1)
  • spawn_listener_supervisor (20-33)
⏰ 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). (10)
  • GitHub Check: Redirect rules - hyprnote-storybook
  • GitHub Check: Header rules - hyprnote-storybook
  • GitHub Check: Pages changed - hyprnote-storybook
  • GitHub Check: Redirect rules - hyprnote
  • GitHub Check: Header rules - hyprnote
  • GitHub Check: Pages changed - hyprnote
  • GitHub Check: ci (linux, depot-ubuntu-22.04-8)
  • GitHub Check: ci (linux, depot-ubuntu-24.04-8)
  • GitHub Check: ci (macos, depot-macos-14)
  • GitHub Check: fmt
🔇 Additional comments (12)
apps/desktop/src-tauri/Cargo.toml (1)

67-68: LGTM!

The workspace dependencies for ractor and ractor-supervisor are correctly added, following the existing pattern used throughout the file.

plugins/local-stt/src/server/supervisor.rs (1)

19-41: Clean refactoring and parent linkage implementation.

The extraction of make_supervisor_options() improves readability, and the optional parent linkage pattern is correctly implemented. The supervisor is only linked after successful spawn.

apps/desktop/src-tauri/src/lib.rs (2)

17-21: Verify the supervisor handle lifetime.

The _root_supervisor_handle is captured but not held beyond this destructuring. While JoinHandle doesn't cancel on drop by default, storing it somewhere (e.g., in app state) would ensure the task can be awaited on shutdown for graceful termination and proper cleanup.


85-94: LGTM!

The InitOptions pattern consistently passes the root supervisor's cell to both plugins, with graceful fallback to None if the root supervisor failed to spawn. This enables optional supervision hierarchy while maintaining backward compatibility.

plugins/listener/src/supervisor.rs (1)

20-33: LGTM!

The spawn_listener_supervisor function correctly implements the optional parent linkage pattern, consistent with the STT supervisor implementation.

plugins/local-stt/src/lib.rs (2)

31-34: LGTM!

InitOptions with #[derive(Default)] provides backward compatibility, allowing callers to use Default::default() when no parent supervision is needed.


57-94: LGTM!

The updated init function correctly accepts InitOptions, passes the parent supervisor to the async spawn, and handles errors gracefully with logging. The non-blocking async spawn pattern allows plugin setup to complete while the supervisor initializes in the background.

apps/desktop/src-tauri/src/supervisor.rs (2)

1-8: LGTM on imports and type aliases.

The type aliases provide clean abstraction over the ractor types and align with the pattern used in plugins/listener/src/supervisor.rs.


12-29: API usage is correct and verified; code follows the established pattern.

The review's observation is accurate: spawn_root_supervisor() returns Option while spawn_listener_supervisor() returns Result, and both use the same underlying DynamicSupervisor::spawn() API. However, this reflects a deliberate design choice rather than an error.

Verified facts:

  • Both functions use identical DynamicSupervisor::spawn(...).await calls
  • The desktop supervisor converts the underlying Result to Option via explicit matching
  • The listener supervisor propagates the Result directly with ?
  • The local-stt supervisor also uses Result propagation, showing multiple patterns in the codebase
  • The call site in lib.rs handles Option by mapping None to None values without specialized error logic

Assessment: The implementation is correct and consistent with the codebase patterns. The suggestion to use Result instead of Option is architecturally valid but remains optional—both approaches are used across different supervisors in the project.

plugins/listener/src/lib.rs (3)

1-2: LGTM on supervision integration imports and exports.

The module structure cleanly separates supervisor logic and re-exports the necessary types for consumers.

Also applies to: 12-12, 17-17


21-21: State fields are now public - verify this is intentional.

Making app, listener_supervisor, and supervisor_handle public exposes internal state. If this is intentional for external access (e.g., by the desktop app or other plugins), this is fine. Otherwise, consider providing accessor methods instead.

Also applies to: 23-27


29-32: LGTM on InitOptions.

Deriving Default is a good choice for backward compatibility - callers can use InitOptions::default() when no parent supervisor is needed.

@yujonglee yujonglee merged commit 09824ef into main Nov 25, 2025
17 checks passed
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