diff --git a/crates/miroir-core/src/task_store/redis.rs b/crates/miroir-core/src/task_store/redis.rs index 3281bcd..7657b91 100644 --- a/crates/miroir-core/src/task_store/redis.rs +++ b/crates/miroir-core/src/task_store/redis.rs @@ -53,24 +53,25 @@ impl RedisPool { /// Block on an async future using a dedicated runtime. - /// Always spawns a fresh thread with its own single-threaded runtime to - /// avoid "cannot start a runtime from within a runtime" panics. + /// Spawns a dedicated thread with its own single-threaded runtime to avoid + /// "cannot start a runtime from within a runtime" panics when called from + /// within an existing tokio runtime (e.g., in tests). fn block_on(&self, future: F) -> F::Output where F: std::future::Future + Send + 'static, F::Output: Send + 'static, { - std::thread::scope(|s| { - s.spawn(|| { - let rt = tokio::runtime::Builder::new_current_thread() - .enable_all() - .build() - .expect("Failed to create runtime in thread"); - rt.block_on(future) - }) - .join() - .unwrap_or_else(|_| panic!("block_on thread panicked")) + // Spawn a dedicated thread to run the async future + // This avoids conflicts with any existing tokio runtime + std::thread::spawn(move || { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .expect("Failed to create runtime in thread"); + rt.block_on(future) }) + .join() + .unwrap_or_else(|_| panic!("block_on thread panicked")) } } @@ -112,6 +113,15 @@ impl RedisTaskStore { self.pool.block_on(future) } + /// Helper: run an async future and return a Result, for use in methods that return Result. + fn block_on_result(&self, future: F) -> Result + where + F: std::future::Future> + Send + 'static, + T: Send + 'static, + { + self.pool.block_on(future) + } + /// Helper: parse a hash row into a TaskRow. fn task_from_hash( miroir_id: String,