Skip to content

Commit

Permalink
switch to spawning worker from a static script
Browse files Browse the repository at this point in the history
  • Loading branch information
zvolin committed May 10, 2024
1 parent 662e808 commit 0495d05
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 38 deletions.
18 changes: 15 additions & 3 deletions node-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ blockstore = { workspace = true }
celestia-tendermint = { workspace = true }

anyhow = "1.0.71"
enum-as-inner = "0.6"
console_error_panic_hook = "0.1.7"
futures = "0.3"
gloo-timers = "0.3"
Expand All @@ -40,11 +41,22 @@ serde-wasm-bindgen = "0.6.0"
serde_repr = "0.1"
thiserror = "1.0"
time = { version = "0.3", features = ["wasm-bindgen"] }
tokio = { version = "*", features = ["sync"]}
tokio = { version = "*", features = ["sync"] }
tracing = "0.1.37"
tracing-subscriber = { version = "0.3.18", features = ["time"] }
tracing-web = "0.1.2"
wasm-bindgen = "0.2.88"
wasm-bindgen-futures = "0.4.37"
web-sys = { version = "0.3.69", features = ["BroadcastChannel", "MessageEvent", "Worker", "WorkerOptions", "WorkerType", "SharedWorker", "MessagePort", "SharedWorkerGlobalScope", "Blob", "BlobPropertyBag", "Url"]}
enum-as-inner = "0.6"
web-sys = { version = "0.3.69", features = [
"Blob",
"BlobPropertyBag",
"BroadcastChannel",
"MessageEvent",
"MessagePort",
"SharedWorker",
"SharedWorkerGlobalScope",
"Url",
"Worker",
"WorkerOptions",
"WorkerType",
] }
24 changes: 24 additions & 0 deletions node-wasm/js/worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// this file should be installed by wasm-pack in pkg/snippets/<pkg-name>-<hash>/js/
import init, { run_worker } from '../../../lumina_node_wasm.js';

// get the path to this file
export function worker_script_url() {
return import.meta.url;
}

// if we are in a worker
if (
typeof WorkerGlobalScope !== 'undefined'
&& self instanceof WorkerGlobalScope
) {
Error.stackTraceLimit = 99;

let queued = [];
onconnect = (event) => {
console.log("Queued connection", event);
queued.push(event.ports[0]);
}

await init();
await run_worker(queued);
}
2 changes: 1 addition & 1 deletion node-wasm/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl NodeDriver {
/// already have been started. Otherwise it needs to be started with [`NodeDriver::start`].
#[wasm_bindgen(constructor)]
pub async fn new() -> Result<NodeDriver> {
let worker = spawn_worker(LUMINA_SHARED_WORKER_NAME, "/wasm/lumina_node_wasm.js")?;
let worker = spawn_worker(LUMINA_SHARED_WORKER_NAME)?;

let onerror_callback: Closure<dyn Fn(MessageEvent)> = Closure::new(|ev: MessageEvent| {
error!("received error from SharedWorker: {:?}", ev.to_string());
Expand Down
44 changes: 10 additions & 34 deletions node-wasm/src/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use thiserror::Error;
use tokio::sync::mpsc;
use tracing::{debug, error, info, warn};
use wasm_bindgen::prelude::*;
use web_sys::{Blob, BlobPropertyBag, MessagePort, SharedWorker, Url, WorkerOptions, WorkerType};
use web_sys::{MessagePort, SharedWorker, WorkerOptions, WorkerType};

use lumina_node::node::{Node, NodeError};
use lumina_node::store::{IndexedDbStore, SamplingMetadata, Store, StoreError};
Expand Down Expand Up @@ -307,39 +307,9 @@ pub async fn run_worker(queued_connections: Vec<MessagePort>) {
info!("Channel to WorkerMessageServer closed, exiting the SharedWorker");
}

/// SharedWorker can only be spawned from an [`URL`]. To eliminate a need to host a js shim
/// which calls into our Rust wasm code under specific path, we encode its entire contents
/// as a [`Blob`] which is then passed as an URL.
///
/// [`URL`]: https://developer.mozilla.org/en-US/docs/Web/API/URL
/// ['Blob']: https://developer.mozilla.org/en-US/docs/Web/API/Blob
pub(crate) fn spawn_worker(name: &str, wasm_url: &str) -> Result<SharedWorker, JsError> {
let script = format!(
r#"
Error.stackTraceLimit = 99;
let queued = [];
onconnect = (event) => {{
console.log("Queued connection", event);
queued.push(event.ports[0]);
}}
self.lumina = await import(self.location.origin + '{wasm_url}');
await self.lumina.default();
await self.lumina.run_worker(queued);
"#
);

let array = Array::new();
array.push(&script.into());
let blob = Blob::new_with_str_sequence_and_options(
&array,
BlobPropertyBag::new().type_("application/javascript"),
)
.to_error("could not create js shim Blob")?;

let url =
Url::create_object_url_with_blob(&blob).to_error("could not create js shim Blob Url")?;
/// Spawn a new SharedWorker.
pub(crate) fn spawn_worker(name: &str) -> Result<SharedWorker, JsError> {
let url = worker_script_url();

let mut opts = WorkerOptions::new();
opts.type_(WorkerType::Module);
Expand All @@ -350,3 +320,9 @@ await self.lumina.run_worker(queued);

Ok(worker)
}

#[wasm_bindgen(module = "/js/worker.js")]
extern "C" {
// must be called in order to include this script in generated package
fn worker_script_url() -> String;
}

0 comments on commit 0495d05

Please sign in to comment.