From dab8d3e30c375e9b131bbffd65b97477352d120d Mon Sep 17 00:00:00 2001 From: James Kay Date: Fri, 13 Sep 2024 22:40:10 +0100 Subject: [PATCH] Add threading on the Web Use the `wasm_thread` library to enable real `spawn_blocking` on the Web in `linera_base::task`. --- Cargo.lock | 14 +++++++++++++- Cargo.toml | 1 + examples/Cargo.lock | 1 - linera-base/Cargo.toml | 2 ++ linera-base/src/task.rs | 6 +++++- linera-execution/Cargo.toml | 2 +- linera-storage/Cargo.toml | 4 ---- linera-storage/build.rs | 2 +- linera-storage/src/lib.rs | 7 ++++--- 9 files changed, 27 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 875bc649e943..7a934856c92b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4231,6 +4231,7 @@ dependencies = [ "tracing-subscriber", "tracing-web", "wasm-bindgen-futures", + "wasm_thread", "wasmtimer", "web-time", "zstd", @@ -4747,7 +4748,6 @@ dependencies = [ "linera-views", "prometheus", "serde", - "tokio", ] [[package]] @@ -8487,6 +8487,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm_thread" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22bc95de7e96023c115820c1b87504cdd316ed958d2dfb97dca502cc6e5772a1" +dependencies = [ + "futures", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasmer-config" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 66344d7169c9..97afc848461b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -159,6 +159,7 @@ wasm-bindgen-futures = "0.4.42" wasm-bindgen-test = "0.3.42" wasm-encoder = "0.24.1" wasm-instrument = "0.4.0" +wasm_thread = "0.3.0" wasmer = { package = "linera-wasmer", version = "4.3.6-linera.3", default-features = false } wasmer-compiler-singlepass = { package = "linera-wasmer-compiler-singlepass", version = "4.3.6-linera.3" } wasmparser = "0.101.1" diff --git a/examples/Cargo.lock b/examples/Cargo.lock index e2f9f39cadf4..202a6f1ef538 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -3497,7 +3497,6 @@ dependencies = [ "linera-views", "prometheus", "serde", - "tokio", ] [[package]] diff --git a/linera-base/Cargo.toml b/linera-base/Cargo.toml index cc8870f5e91c..d08db170d77d 100644 --- a/linera-base/Cargo.toml +++ b/linera-base/Cargo.toml @@ -23,6 +23,7 @@ web = [ "tracing-web", "wasmtimer", "wasm-bindgen-futures", + "wasm_thread", "web-time", ] @@ -57,6 +58,7 @@ tokio = { workspace = true, features = ["time"] } tracing.workspace = true tracing-subscriber = { workspace = true, features = ["json", "fmt", "ansi"] } wasm-bindgen-futures = { workspace = true, optional = true } +wasm_thread = { workspace = true, optional = true } wasmtimer = { workspace = true, optional = true } web-time = { workspace = true, optional = true } diff --git a/linera-base/src/task.rs b/linera-base/src/task.rs index 967a170d9b7a..327b23618690 100644 --- a/linera-base/src/task.rs +++ b/linera-base/src/task.rs @@ -60,7 +60,11 @@ mod implementation { pub fn spawn_blocking R + Send + 'static>( task: F, ) -> BlockingFuture { - spawn(async { task() }) + let (send, recv) = oneshot::channel(); + wasm_thread::spawn(move || { + let _ = send.send(task()); + }); + recv } } diff --git a/linera-execution/Cargo.toml b/linera-execution/Cargo.toml index 3861695c5923..830da022b2b4 100644 --- a/linera-execution/Cargo.toml +++ b/linera-execution/Cargo.toml @@ -68,7 +68,7 @@ wasmer = { workspace = true, optional = true, features = ["sys-default", "single [target.'cfg(target_arch = "wasm32")'.dependencies] tokio = { workspace = true, features = ["rt"] } -wasmer = { workspace = true, optional = true, features = ["js-default"] } +wasmer = { workspace = true, optional = true, features = ["js-default", "js-serializable-module"] } [dev-dependencies] anyhow.workspace = true diff --git a/linera-storage/Cargo.toml b/linera-storage/Cargo.toml index 038a83041f18..f4f6923adb3c 100644 --- a/linera-storage/Cargo.toml +++ b/linera-storage/Cargo.toml @@ -13,9 +13,6 @@ version.workspace = true [features] test = [ - "tokio/rt", - "tokio/test-util", - "tokio/time", "linera-execution/test", "linera-views/test", ] @@ -45,7 +42,6 @@ linera-execution.workspace = true linera-views.workspace = true prometheus.workspace = true serde.workspace = true -tokio = { workspace = true, features = ["macros"] } [dev-dependencies] anyhow.workspace = true diff --git a/linera-storage/build.rs b/linera-storage/build.rs index 8bd13c49331b..1c65763080ab 100644 --- a/linera-storage/build.rs +++ b/linera-storage/build.rs @@ -5,7 +5,7 @@ fn main() { cfg_aliases::cfg_aliases! { with_testing: { any(test, feature = "test") }, with_metrics: { all(not(target_arch = "wasm32"), feature = "metrics") }, - with_wasmer: { all(not(target_arch = "wasm32"), feature = "wasmer") }, + with_wasmer: { all(any(feature = "web", not(target_arch = "wasm32")), feature = "wasmer") }, with_wasmtime: { all(not(target_arch = "wasm32"), feature = "wasmtime") }, with_wasm_runtime: { any(with_wasmer, with_wasmtime) }, }; diff --git a/linera-storage/src/lib.rs b/linera-storage/src/lib.rs index 7a0e72fddff9..d6a24bd48d49 100644 --- a/linera-storage/src/lib.rs +++ b/linera-storage/src/lib.rs @@ -193,7 +193,7 @@ pub trait Storage: Sized { let mut tasks = Vec::new(); for key in keys { let client = self.clone(); - tasks.push(tokio::task::spawn(async move { + tasks.push(linera_base::task::spawn(async move { client.read_certificate(key).await })); } @@ -295,7 +295,7 @@ pub trait Storage: Sized { .into_inner_contract_bytecode() .expect("Contract Bytecode Blob is of the wrong Blob type!"); let contract_bytecode = - tokio::task::spawn_blocking(move || compressed_contract_bytecode.decompress()) + linera_base::task::spawn_blocking(move || compressed_contract_bytecode.decompress()) .await??; Ok(Arc::new( WasmContractModule::new(contract_bytecode, wasm_runtime).await?, @@ -333,7 +333,8 @@ pub trait Storage: Sized { .into_inner_service_bytecode() .expect("Service Bytecode Blob is of the wrong Blob type!"); let service_bytecode = - tokio::task::spawn_blocking(move || compressed_service_bytecode.decompress()).await??; + linera_base::task::spawn_blocking(move || compressed_service_bytecode.decompress()) + .await??; Ok(Arc::new( WasmServiceModule::new(service_bytecode, wasm_runtime).await?, ))