diff --git a/Cargo.lock b/Cargo.lock index 394379d..2dfd579 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -673,7 +673,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror", + "thiserror 2.0.19", ] [[package]] @@ -1042,6 +1042,27 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "displaydoc" version = "0.2.6" @@ -1937,7 +1958,7 @@ dependencies = [ "jni-sys", "log", "simd_cesu8", - "thiserror", + "thiserror 2.0.19", "walkdir", "windows-link", ] @@ -2057,6 +2078,15 @@ dependencies = [ "cc", ] +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +dependencies = [ + "libc", +] + [[package]] name = "linkme" version = "0.3.37" @@ -2654,7 +2684,7 @@ dependencies = [ "rustc-hash 2.1.3", "rustls", "socket2", - "thiserror", + "thiserror 2.0.19", "tokio", "tracing", "web-time", @@ -2677,7 +2707,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror", + "thiserror 2.0.19", "tinyvec", "tracing", "web-time", @@ -2856,6 +2886,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 1.0.69", +] + [[package]] name = "regalloc2" version = "0.13.5" @@ -3582,7 +3623,7 @@ dependencies = [ "tantivy-stacker", "tantivy-tokenizer-api", "tempfile", - "thiserror", + "thiserror 2.0.19", "time", "typetag", "uuid", @@ -3718,13 +3759,33 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + [[package]] name = "thiserror" version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.19", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] @@ -4084,7 +4145,7 @@ checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" dependencies = [ "crossbeam-channel", "symlink", - "thiserror", + "thiserror 2.0.19", "time", "tracing-subscriber", ] @@ -4152,7 +4213,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b6c49aecd4abae3ffa88ab1e28b3de7a7497a9732be828e3a6f1855b6ea80fd" dependencies = [ "mimalloc", - "thiserror", + "thiserror 2.0.19", "tracing", "tracing-subscriber", "turso_core", @@ -4219,7 +4280,7 @@ dependencies = [ "strum_macros", "tantivy", "tempfile", - "thiserror", + "thiserror 2.0.19", "tracing", "tracing-subscriber", "turso_ext", @@ -4264,7 +4325,7 @@ dependencies = [ "miette", "strum", "strum_macros", - "thiserror", + "thiserror 2.0.19", "turso_macros", ] @@ -4312,7 +4373,7 @@ dependencies = [ "roaring", "serde", "serde_json", - "thiserror", + "thiserror 2.0.19", "tracing", "turso_core", "turso_parser", @@ -4645,7 +4706,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror", + "thiserror 2.0.19", "toasty", "toasty-driver-turso", "tokio", @@ -4668,7 +4729,7 @@ dependencies = [ "serde_json", "sha2", "tempfile", - "thiserror", + "thiserror 2.0.19", "toml", "wit-component 0.243.0", "wit-parser 0.243.0", @@ -4680,7 +4741,7 @@ name = "wasmeld-runtime" version = "0.1.0" dependencies = [ "serde", - "thiserror", + "thiserror 2.0.19", "toml", "wasmeld-package", "wasmtime", @@ -4755,6 +4816,7 @@ dependencies = [ "target-lexicon", "wasmparser 0.243.0", "wasmtime-environ", + "wasmtime-internal-cache", "wasmtime-internal-component-macro", "wasmtime-internal-component-util", "wasmtime-internal-cranelift", @@ -4794,6 +4856,26 @@ dependencies = [ "wasmtime-internal-component-util", ] +[[package]] +name = "wasmtime-internal-cache" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a31a582632f47753e4a9a5412ab5edfbc05a6df9031336a2f2eff46a70a1cac" +dependencies = [ + "base64 0.22.1", + "directories-next", + "log", + "postcard", + "rustix 1.1.4", + "serde", + "serde_derive", + "sha2", + "toml", + "wasmtime-environ", + "windows-sys 0.61.2", + "zstd", +] + [[package]] name = "wasmtime-internal-component-macro" version = "41.0.0" @@ -4834,7 +4916,7 @@ dependencies = [ "pulley-interpreter", "smallvec", "target-lexicon", - "thiserror", + "thiserror 2.0.19", "wasmparser 0.243.0", "wasmtime-environ", "wasmtime-internal-math", @@ -4969,7 +5051,7 @@ dependencies = [ "io-lifetimes", "rustix 1.1.4", "system-interface", - "thiserror", + "thiserror 2.0.19", "tokio", "tracing", "url", @@ -5076,7 +5158,7 @@ dependencies = [ "regalloc2", "smallvec", "target-lexicon", - "thiserror", + "thiserror 2.0.19", "wasmparser 0.243.0", "wasmtime-environ", "wasmtime-internal-cranelift", @@ -5540,7 +5622,7 @@ dependencies = [ "flate2", "indexmap", "memchr", - "thiserror", + "thiserror 2.0.19", "zopfli", ] diff --git a/Cargo.toml b/Cargo.toml index fcec5ea..db8af12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ toml = "0.9.8" tower-http = { version = "0.7.0", features = ["cors", "trace"] } tracing = "0.1.44" tracing-subscriber = { version = "0.3.23", features = ["env-filter", "fmt"] } -wasmtime = { version = "=41.0.0", default-features = false, features = ["component-model", "cranelift", "runtime", "std"] } +wasmtime = { version = "=41.0.0", default-features = false, features = ["cache", "component-model", "cranelift", "runtime", "std"] } wasmtime-wasi = { version = "=41.0.0", default-features = false, features = ["p2"] } wit-bindgen = "=0.41.0" wit-component = "=0.243.0" diff --git a/crates/wasmeld-runtime/src/error.rs b/crates/wasmeld-runtime/src/error.rs index 4b22831..1a56e12 100644 --- a/crates/wasmeld-runtime/src/error.rs +++ b/crates/wasmeld-runtime/src/error.rs @@ -1,6 +1,6 @@ //! Runtime error taxonomy exposed to management layers. -use std::time::Duration; +use std::{path::PathBuf, time::Duration}; use thiserror::Error; @@ -36,6 +36,16 @@ pub enum RuntimeError { #[error("runtime creation failed: {0}")] RuntimeCreation(#[source] wasmtime::Error), + #[error("failed to prepare Component compilation cache {path}: {source}")] + CacheDirectory { + path: PathBuf, + #[source] + source: std::io::Error, + }, + + #[error("invalid Component compilation cache configuration: {0}")] + CacheConfiguration(#[source] wasmtime::Error), + #[error("failed to read component artifact {path}: {source}")] ArtifactRead { path: String, diff --git a/crates/wasmeld-runtime/src/runtime.rs b/crates/wasmeld-runtime/src/runtime.rs index 6322273..3560485 100644 --- a/crates/wasmeld-runtime/src/runtime.rs +++ b/crates/wasmeld-runtime/src/runtime.rs @@ -8,6 +8,7 @@ use std::{ collections::HashMap, fs, + path::PathBuf, sync::{ Arc, Mutex, atomic::{AtomicBool, Ordering}, @@ -18,7 +19,7 @@ use std::{ }; use wasmtime::{ - Config, Engine, Store, StoreLimits, StoreLimitsBuilder, + Cache, CacheConfig, Config, Engine, Store, StoreLimits, StoreLimitsBuilder, component::{Component, HasData, Linker, ResourceTable}, }; use wasmtime_wasi::{ @@ -61,6 +62,8 @@ pub struct RuntimeConfig { pub epoch_tick: Duration, /// Maximum native stack reservation for WebAssembly execution. pub max_wasm_stack: usize, + /// Optional persistent cache for compiled Component machine code. + pub component_cache_dir: Option, /// Service-scoped storage used by Components importing the KV capability. pub kv_backend: Option>, } @@ -70,6 +73,7 @@ impl Default for RuntimeConfig { Self { epoch_tick: DEFAULT_EPOCH_TICK, max_wasm_stack: DEFAULT_MAX_WASM_STACK, + component_cache_dir: None, kv_backend: None, } } @@ -180,6 +184,21 @@ impl Runtime { wasmtime_config.consume_fuel(true); wasmtime_config.epoch_interruption(true); wasmtime_config.max_wasm_stack(config.max_wasm_stack); + if let Some(cache_dir) = &config.component_cache_dir { + fs::create_dir_all(cache_dir).map_err(|source| RuntimeError::CacheDirectory { + path: cache_dir.clone(), + source, + })?; + let cache_dir = + fs::canonicalize(cache_dir).map_err(|source| RuntimeError::CacheDirectory { + path: cache_dir.clone(), + source, + })?; + let mut cache_config = CacheConfig::new(); + cache_config.with_directory(cache_dir); + let cache = Cache::new(cache_config).map_err(RuntimeError::CacheConfiguration)?; + wasmtime_config.cache(Some(cache)); + } let engine = Arc::new(Engine::new(&wasmtime_config).map_err(RuntimeError::RuntimeCreation)?);