Fix: Panic 'no reactor running' in verified_lists background refresh#121
Fix: Panic 'no reactor running' in verified_lists background refresh#121sentry[bot] wants to merge 1 commit into
Conversation
| pub async fn get_collection_verification(game_domain: String, slug: String) -> VerifiedEntry { | ||
| verified_lists::maybe_refresh_in_background(); | ||
| verified_lists::collection_status(&game_domain, &slug) | ||
| } | ||
|
|
||
| #[tauri::command] | ||
| pub fn get_wabbajack_verification(modlist_name: String) -> VerifiedEntry { | ||
| pub async fn get_wabbajack_verification(modlist_name: String) -> VerifiedEntry { | ||
| verified_lists::maybe_refresh_in_background(); | ||
| verified_lists::wabbajack_status(&modlist_name) | ||
| } | ||
|
|
||
| #[tauri::command] | ||
| pub fn get_verification_manifest() -> Manifest { | ||
| pub async fn get_verification_manifest() -> Manifest { | ||
| verified_lists::maybe_refresh_in_background(); | ||
| verified_lists::full_manifest() | ||
| } |
There was a problem hiding this comment.
Blocking I/O on async worker thread on first call
maybe_refresh_in_background() calls ensure_initialized(), which on its first invocation falls through to load_disk_cache() → std::fs::read(...). Previously, as pub fn commands, these ran on Tauri's blocking thread pool where synchronous I/O is explicitly allowed. As pub async fn, they run on Tokio's async worker threads, and a blocking std::fs::read there will stall a worker thread for the duration of the read. The disk file is small and initialization only happens once per process, so the practical risk is low — but the correct long-term fix would be to use tokio::fs::read inside an async ensure_initialized (or call the existing sync path via tokio::task::spawn_blocking).
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Summary
This PR resolves a panic (
there is no reactor running, must be called from the context of a Tokio 1.x runtime) that occurred when synchronous Tauri commands invokedcorkscrew_lib::verified_lists::maybe_refresh_in_background.The root cause was that synchronous Tauri commands execute on a blocking thread pool, which lacks the necessary Tokio runtime context for
tauri::async_runtime::spawnto function correctly. Althoughtauri::async_runtime::spawnis designed to be runtime-agnostic, its underlying implementation (delegating totokio::task::spawnin Tauri 2) still requires an active Tokio reactor.Changes
get_collection_verification,get_wabbajack_verification, andget_verification_manifest) frompub fntopub async fn. This ensures they are executed on Tauri's internal Tokio runtime, providing the required reactor context formaybe_refresh_in_backgroundto safely spawn its background refresh task.verified_lists.rsregarding the safety oftauri::async_runtime::spawnfor clarity.Testing
cargo test -p corkscrewpassesnpx svelte-check --threshold errorpassescargo tauri dev(if UI changes)Fixes RUST-B
Greptile Summary
Converts three synchronous Tauri commands (
get_collection_verification,get_wabbajack_verification,get_verification_manifest) toasync fnso thatmaybe_refresh_in_background's internaltauri::async_runtime::spawncall has a live Tokio reactor, eliminating the "no reactor running" panic. The companion comment inverified_lists.rsis updated to accurately document this constraint..awaitany work themselves;asyncis used solely to opt into Tauri's runtime thread pool rather than the blocking pool.get_verification_cache_age_secs(which does not callmaybe_refresh_in_background) is correctly left aspub fn.verified_lists.rsnow clearly warns thatmaybe_refresh_in_backgroundmust only be called from an async context.Confidence Score: 4/5
Safe to merge — the fix correctly eliminates the runtime panic and the only remaining concern is a minor blocking I/O call that now runs on an async thread.
The root-cause analysis is sound and the change is minimal and targeted. The one thing to keep in mind is that
ensure_initialized()can do a synchronousstd::fs::readon the first command invocation; this was previously safe on Tauri's blocking thread pool but now executes on an async worker thread. The file is small and initialization is one-shot, so it won't cause problems in practice, but it's worth tracking for a future cleanup.src-tauri/src/commands/verified_lists_cmds.rs — the blocking disk I/O path in
ensure_initializedis now reachable from an async worker thread for the first time.Important Files Changed
pub fntopub async fnto provide a Tokio runtime context formaybe_refresh_in_background; the three affected commands do not.awaitanything themselves, soasyncis used purely for runtime context. A minor concern exists:ensure_initialized()may do blocking disk I/O on the first call, which now runs on an async worker thread rather than Tauri's blocking pool.maybe_refresh_in_backgroundupdated to accurately reflect that callers must be async and that calling from a sync command would panic; no logic changes.Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant Frontend participant TauriRuntime as Tauri Async Runtime participant Cmd as verified_lists_cmds (async fn) participant VL as verified_lists participant BG as Background Refresh Task Frontend->>TauriRuntime: invoke("get_collection_verification") TauriRuntime->>Cmd: dispatch on async worker thread Cmd->>VL: maybe_refresh_in_background() VL->>VL: ensure_initialized() / check TTL alt cache stale or missing VL->>TauriRuntime: tauri::async_runtime::spawn(refresh_from_remote) TauriRuntime-->>BG: spawned (fire-and-forget) end Cmd->>VL: collection_status(game_domain, slug) VL-->>Cmd: VerifiedEntry Cmd-->>Frontend: VerifiedEntry (returns immediately with cached data)%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant Frontend participant TauriRuntime as Tauri Async Runtime participant Cmd as verified_lists_cmds (async fn) participant VL as verified_lists participant BG as Background Refresh Task Frontend->>TauriRuntime: invoke("get_collection_verification") TauriRuntime->>Cmd: dispatch on async worker thread Cmd->>VL: maybe_refresh_in_background() VL->>VL: ensure_initialized() / check TTL alt cache stale or missing VL->>TauriRuntime: tauri::async_runtime::spawn(refresh_from_remote) TauriRuntime-->>BG: spawned (fire-and-forget) end Cmd->>VL: collection_status(game_domain, slug) VL-->>Cmd: VerifiedEntry Cmd-->>Frontend: VerifiedEntry (returns immediately with cached data)Reviews (1): Last reviewed commit: "Fix: Panic 'no reactor running' in verif..." | Re-trigger Greptile