Refresh unit requests and preserve shared compilation across runtime shutdown
This commit is contained in:
+42
-10
@@ -80,16 +80,10 @@ impl Compiler {
|
||||
.or_insert_with(|| {
|
||||
let (tx, rx) = watch::channel(None);
|
||||
let compiler = self.clone();
|
||||
// The job owns completion even if a command or a precompile waiter is cancelled.
|
||||
tokio::spawn(async move {
|
||||
let result =
|
||||
tokio::task::spawn_blocking(move || compiler.compile(&bytes)).await;
|
||||
tx.send_replace(Some(
|
||||
result
|
||||
.map_err(anyhow::Error::from)
|
||||
.and_then(|r| r)
|
||||
.map_err(|e| format!("{e:#}")),
|
||||
));
|
||||
// Completion must survive the async runtime that started this shared job.
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let result = compiler.compile(&bytes).map_err(|e| format!("{e:#}"));
|
||||
tx.send_replace(Some(result));
|
||||
});
|
||||
rx
|
||||
})
|
||||
@@ -192,6 +186,44 @@ mod tests {
|
||||
use crate::exec::{Command, Exec, Options};
|
||||
use std::{future::Future, sync::atomic::Ordering};
|
||||
|
||||
#[test]
|
||||
fn compilation_survives_the_originating_runtime() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
let compiler = Compiler::new(&temp.path().join("cache")).unwrap();
|
||||
let bytes =
|
||||
wat::parse_str(r#"(module (memory (export "memory") 1) (func (export "_start")))"#)
|
||||
.unwrap();
|
||||
let (started_tx, started_rx) = tokio::sync::oneshot::channel();
|
||||
let (finish_tx, finish_rx) = std::sync::mpsc::channel();
|
||||
*compiler.before_compile.lock().unwrap() = Some(Box::new(move || {
|
||||
started_tx.send(()).unwrap();
|
||||
finish_rx.recv().unwrap();
|
||||
}));
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
runtime.block_on(async {
|
||||
let compiler = compiler.clone();
|
||||
let bytes = bytes.clone();
|
||||
tokio::spawn(async move { compiler.get(bytes).await });
|
||||
started_rx.await.unwrap();
|
||||
});
|
||||
runtime.shutdown_background();
|
||||
finish_tx.send(()).unwrap();
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
runtime.block_on(async {
|
||||
tokio::time::timeout(std::time::Duration::from_secs(10), compiler.get(bytes))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
});
|
||||
assert_eq!(compiler.compilations.load(Ordering::Relaxed), 1);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn command_joins_precompile_even_after_waiter_cancellation() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user