Skip to content

Commit e9b69fb

Browse files
committed
feat: Better transpiled module caching in SW
1 parent aa673af commit e9b69fb

File tree

15 files changed

+274
-144
lines changed

15 files changed

+274
-144
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ members = [
99
resolver = "2"
1010

1111
[workspace.dependencies]
12+
anyhow = { version = "1" }
1213
async-trait = { version = "0.1" }
1314
axum = { version = "0.7" }
1415
blake3 = { version = "1.5" }
@@ -32,6 +33,7 @@ wasm-bindgen = { version = "0.2" }
3233
wasmtime-environ = { version = "20" }
3334
web-sys = { version = "0.3" }
3435
wit-bindgen = { version = "0.25" }
36+
wit-parser = { version = "0.208" }
3537

3638
[profile.release]
3739
opt-level = 'z'

rust/usuba-compat/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ edition = "2021"
77
crate-type = ["cdylib", "rlib"]
88

99
[dependencies]
10+
blake3 = { workspace = true }
1011
js-component-bindgen = { workspace = true }
1112
wit-bindgen = { workspace = true }
1213
wasmtime-environ = { workspace = true, features = ["component-model", "compile"] }

rust/usuba-compat/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ impl Guest for Polyfill {
3030
.map(|transpiled| transpiled.into())
3131
.map_err(|error| format!("{}", error))
3232
}
33+
34+
fn hash(bytes: Vec<u8>) -> String {
35+
blake3::hash(&bytes).to_string()
36+
}
3337
}
3438

3539
export!(Polyfill);

rust/usuba-compat/wit/usuba-compat.wit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ world usuba-compat {
2121
}
2222

2323
export polyfill: func(component: list<u8>, options: polyfill-options) -> result<artifacts, string>;
24+
export hash: func(bytes: list<u8>) -> string;
2425
}

rust/usuba/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ edition = "2021"
77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

99
[dependencies]
10+
anyhow = { workspace = true }
1011
async-trait = { workspace = true }
1112
axum = { workspace = true, features = ["multipart"] }
1213
blake3 = { workspace = true }
@@ -23,5 +24,6 @@ tracing = { workspace = true }
2324
tracing-subscriber = { workspace = true }
2425
utoipa = { workspace = true, features = ["axum_extras"] }
2526
utoipa-swagger-ui = { workspace = true, features = ["axum"] }
27+
wit-parser = { workspace = true }
2628
# gcloud-sdk = { version = "0.24.6", features = ["google-cloud-aiplatform-v1"] }
2729

rust/usuba/src/bake/bake.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,10 @@ use bytes::Bytes;
44

55
#[async_trait]
66
pub trait Bake {
7-
async fn bake(&self, wit: Bytes, source_code: Bytes) -> Result<Bytes, UsubaError>;
7+
async fn bake(
8+
&self,
9+
world: &str,
10+
wit: Vec<Bytes>,
11+
source_code: Bytes,
12+
) -> Result<Bytes, UsubaError>;
813
}

rust/usuba/src/bake/javascript.rs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,38 @@
11
use std::io::Cursor;
2+
use std::path::{Path, PathBuf};
23
use tracing::instrument;
34

5+
use crate::UsubaError;
6+
47
use super::Bake;
58
use async_trait::async_trait;
69
use bytes::Bytes;
710
use tempfile::TempDir;
811

912
use tokio::process::Command;
13+
use tokio::task::JoinSet;
14+
15+
use wit_parser::UnresolvedPackage;
16+
17+
async fn write_file(path: PathBuf, bytes: Bytes) -> Result<(), UsubaError> {
18+
let mut file = tokio::fs::File::create(&path).await?;
19+
let mut cursor = Cursor::new(bytes.as_ref());
20+
tokio::io::copy(&mut cursor, &mut file).await?;
21+
Ok(())
22+
}
1023

1124
#[derive(Debug)]
1225
pub struct JavaScriptBaker {}
1326

1427
#[async_trait]
1528
impl Bake for JavaScriptBaker {
1629
#[instrument]
17-
async fn bake(&self, wit: Bytes, source_code: Bytes) -> Result<Bytes, crate::UsubaError> {
30+
async fn bake(
31+
&self,
32+
world: &str,
33+
wit: Vec<Bytes>,
34+
source_code: Bytes,
35+
) -> Result<Bytes, crate::UsubaError> {
1836
let workspace = TempDir::new()?;
1937
debug!(
2038
"Created temporary workspace in {}",
@@ -23,31 +41,32 @@ impl Bake for JavaScriptBaker {
2341

2442
let wasm_path = workspace.path().join("module.wasm");
2543
let js_path = workspace.path().join("module.js");
26-
let wit_path = workspace.path().join("module.wit");
2744

28-
let (mut wit_file, mut js_file) = tokio::try_join!(
29-
tokio::fs::File::create(&wit_path),
30-
tokio::fs::File::create(&js_path),
31-
)?;
45+
debug!(?workspace, "Created temporary workspace");
3246

33-
debug!(?wit_path, ?js_path, "Created temporary input files");
47+
let mut writes = JoinSet::new();
3448

35-
let mut wit_cursor = Cursor::new(wit);
36-
let mut js_cursor = Cursor::new(source_code);
49+
wit.into_iter()
50+
.enumerate()
51+
.map(|(i, wit)| write_file(workspace.path().join(format!("module{}.wit", i)), wit))
52+
.chain([write_file(js_path.clone(), source_code)])
53+
.for_each(|fut| {
54+
writes.spawn(fut);
55+
});
3756

38-
tokio::try_join!(
39-
tokio::io::copy(&mut wit_cursor, &mut wit_file),
40-
tokio::io::copy(&mut js_cursor, &mut js_file),
41-
)?;
57+
while let Some(result) = writes.try_join_next() {
58+
result??;
59+
continue;
60+
}
4261

43-
debug!(?wit_path, ?js_path, "Populated temporary input files");
62+
debug!(?workspace, "Populated temporary input files");
4463

4564
let mut command = Command::new("jco");
4665

4766
command
4867
.arg("componentize")
4968
.arg("-w")
50-
.arg(wit_path.display().to_string())
69+
.arg(workspace.path())
5170
.arg("-o")
5271
.arg(wasm_path.display().to_string())
5372
.arg(js_path.display().to_string());

rust/usuba/src/bake/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,14 @@ pub enum Baker {
1313

1414
#[async_trait]
1515
impl Bake for Baker {
16-
async fn bake(&self, wit: Bytes, source_code: Bytes) -> Result<Bytes, crate::UsubaError> {
16+
async fn bake(
17+
&self,
18+
world: &str,
19+
wit: Vec<Bytes>,
20+
source_code: Bytes,
21+
) -> Result<Bytes, crate::UsubaError> {
1722
match self {
18-
Baker::JavaScript => (JavaScriptBaker {}).bake(wit, source_code).await,
23+
Baker::JavaScript => (JavaScriptBaker {}).bake(world, wit, source_code).await,
1924
}
2025
}
2126
}

rust/usuba/src/error.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use blake3::HexError;
55
use redb::{CommitError, DatabaseError, StorageError, TableError, TransactionError};
66
use serde::{Deserialize, Serialize};
77
use thiserror::Error;
8+
use tokio::task::JoinError;
89
use tracing::subscriber::SetGlobalDefaultError;
910
use utoipa::ToSchema;
1011

@@ -16,6 +17,8 @@ pub enum UsubaError {
1617
BakeFailure(String),
1718
#[error("Invalid configuration: {0}")]
1819
InvalidConfiguration(String),
20+
#[error("Invalid module: {0}")]
21+
InvalidModule(String),
1922
#[error("Module not found")]
2023
ModuleNotFound,
2124
#[error("An internal error occurred")]
@@ -89,10 +92,23 @@ impl From<HexError> for UsubaError {
8992
}
9093
}
9194

95+
impl From<JoinError> for UsubaError {
96+
fn from(value: JoinError) -> Self {
97+
UsubaError::Internal(format!("{}", value))
98+
}
99+
}
100+
101+
impl From<anyhow::Error> for UsubaError {
102+
fn from(value: anyhow::Error) -> Self {
103+
todo!()
104+
}
105+
}
106+
92107
impl IntoResponse for UsubaError {
93108
fn into_response(self) -> axum::response::Response {
94109
let status = match self {
95110
UsubaError::BadRequest => StatusCode::BAD_REQUEST,
111+
UsubaError::InvalidModule(_) => StatusCode::BAD_REQUEST,
96112
UsubaError::BakeFailure(_) => StatusCode::INTERNAL_SERVER_ERROR,
97113
UsubaError::InvalidConfiguration(_) => StatusCode::BAD_REQUEST,
98114
UsubaError::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,

0 commit comments

Comments
 (0)