wasmer_wasix/runtime/module_cache/
shared.rs

1use dashmap::DashMap;
2use wasmer::{Engine, Module};
3
4use crate::runtime::module_cache::{CacheError, ModuleCache};
5use wasmer_types::ModuleHash;
6
7/// A [`ModuleCache`] based on a <code>[DashMap]<[ModuleHash], [Module]></code>.
8#[derive(Debug, Default, Clone)]
9pub struct SharedCache {
10    modules: DashMap<(ModuleHash, String), Module>,
11}
12
13impl SharedCache {
14    pub fn new() -> SharedCache {
15        SharedCache::default()
16    }
17}
18
19#[async_trait::async_trait]
20impl ModuleCache for SharedCache {
21    #[tracing::instrument(level = "debug", skip_all, fields(%key))]
22    async fn load(&self, key: ModuleHash, engine: &Engine) -> Result<Module, CacheError> {
23        let key = (key, engine.deterministic_id());
24
25        match self.modules.get(&key) {
26            Some(m) => {
27                tracing::debug!("Cache hit!");
28                Ok(m.value().clone())
29            }
30
31            None => Err(CacheError::NotFound),
32        }
33    }
34
35    async fn contains(&self, key: ModuleHash, engine: &Engine) -> Result<bool, CacheError> {
36        let key = (key, engine.deterministic_id().to_string());
37        Ok(self.modules.contains_key(&key))
38    }
39
40    #[tracing::instrument(level = "debug", skip_all, fields(%key))]
41    async fn save(
42        &self,
43        key: ModuleHash,
44        engine: &Engine,
45        module: &Module,
46    ) -> Result<(), CacheError> {
47        let key = (key, engine.deterministic_id().to_string());
48        self.modules.insert(key, module.clone());
49
50        Ok(())
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    const ADD_WAT: &[u8] = br#"(
59        module
60            (func
61                (export "add")
62                (param $x i64)
63                (param $y i64)
64                (result i64)
65                (i64.add (local.get $x) (local.get $y)))
66        )"#;
67
68    #[tokio::test]
69    async fn round_trip_via_cache() {
70        let engine = Engine::default();
71        let module = Module::new(&engine, ADD_WAT).unwrap();
72        let cache = SharedCache::default();
73        let key = ModuleHash::xxhash_from_bytes([0; 8]);
74
75        cache.save(key, &engine, &module).await.unwrap();
76        let round_tripped = cache.load(key, &engine).await.unwrap();
77
78        let exports: Vec<_> = round_tripped
79            .exports()
80            .map(|export| export.name().to_string())
81            .collect();
82        assert_eq!(exports, ["add"]);
83    }
84}