Skip to content

Commit

Permalink
Upgrade wasmtime (#539)
Browse files Browse the repository at this point in the history
* Upgrade wasmtime

* restructure kv storage structure

* use eyre

* rebuild mrf
  • Loading branch information
aumetra authored May 21, 2024
1 parent 6df04f0 commit c4604a7
Show file tree
Hide file tree
Showing 11 changed files with 229 additions and 230 deletions.
274 changes: 137 additions & 137 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions crates/kitsune-wasm-mrf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ tokio = { version = "1.37.0", features = ["fs"] }
tracing = "0.1.40"
triomphe = "0.1.11"
walkdir = "2.5.0"
wasmtime = { version = "20.0.2", default-features = false, features = [
wasmtime = { version = "21.0.0", default-features = false, features = [
"addr2line",
"async",
"component-model",
Expand All @@ -38,13 +38,13 @@ wasmtime = { version = "20.0.2", default-features = false, features = [
"pooling-allocator",
"runtime",
] }
wasmtime-wasi = { version = "20.0.2", default-features = false }
wasmtime-wasi = { version = "21.0.0", default-features = false }

[dev-dependencies]
tempfile = "3.10.1"
tokio = { version = "1.37.0", features = ["macros", "rt"] }
tracing-subscriber = "0.3.18"
wat = "1.208.0"
wat = "1.208.1"

[lints]
workspace = true
13 changes: 8 additions & 5 deletions crates/kitsune-wasm-mrf/example-mrf/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(clippy::missing_safety_doc, clippy::transmute_int_to_bool, unsafe_code)]

use self::{
fep::mrf::keyvalue::{self, Bucket},
fep::mrf::keyvalue::Bucket,
wasi::logging::logging::{self, Level},
};
use rand::{distributions::Alphanumeric, Rng};
Expand Down Expand Up @@ -32,11 +32,14 @@ impl Guest for Mrf {

// We even have a key-value store! Check this out:
let key = generate_random_key();
let bucket = Bucket::open_bucket("example-bucket").unwrap();
let bucket = Bucket::open("example-bucket").unwrap();

keyvalue::set(&bucket, &key, b"world").unwrap();
assert!(keyvalue::exists(&bucket, &key).unwrap());
keyvalue::delete(&bucket, &key).unwrap();
bucket.set(&key, b"world").unwrap();

assert!(bucket.exists(&key).unwrap());
assert_eq!(bucket.get(&key).unwrap(), Some(b"world".to_vec()));

bucket.delete(&key).unwrap();

Ok(activity)
}
Expand Down
12 changes: 6 additions & 6 deletions crates/kitsune-wasm-mrf/src/kv_storage/fs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Backend, BoxError, BucketBackend};
use super::{Backend, BucketBackend};
use color_eyre::eyre;
use std::path::Path;

Expand All @@ -20,7 +20,7 @@ impl FsBackend {
impl Backend for FsBackend {
type Bucket = FsBucketBackend;

async fn open(&self, module_name: &str, name: &str) -> Result<Self::Bucket, BoxError> {
async fn open(&self, module_name: &str, name: &str) -> eyre::Result<Self::Bucket> {
self.inner
.open_tree(format!("{module_name}:{name}"))
.map(|tree| FsBucketBackend { inner: tree })
Expand All @@ -33,23 +33,23 @@ pub struct FsBucketBackend {
}

impl BucketBackend for FsBucketBackend {
async fn exists(&self, key: &str) -> Result<bool, BoxError> {
async fn exists(&self, key: &str) -> eyre::Result<bool> {
self.inner.contains_key(key).map_err(Into::into)
}

async fn delete(&self, key: &str) -> Result<(), BoxError> {
async fn delete(&self, key: &str) -> eyre::Result<()> {
self.inner.remove(key)?;
Ok(())
}

async fn get(&self, key: &str) -> Result<Option<Vec<u8>>, BoxError> {
async fn get(&self, key: &str) -> eyre::Result<Option<Vec<u8>>> {
self.inner
.get(key)
.map(|maybe_val| maybe_val.map(|val| val.to_vec()))
.map_err(Into::into)
}

async fn set(&self, key: &str, value: &[u8]) -> Result<(), BoxError> {
async fn set(&self, key: &str, value: &[u8]) -> eyre::Result<()> {
self.inner.insert(key, value)?;
Ok(())
}
Expand Down
99 changes: 51 additions & 48 deletions crates/kitsune-wasm-mrf/src/kv_storage/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::mrf_wit::v1::fep::mrf::keyvalue;
use async_trait::async_trait;
use color_eyre::eyre;
use derive_more::From;
use enum_dispatch::enum_dispatch;
use std::{error::Error, future::Future};
use std::future::Future;
use wasmtime::component::Resource;

pub use self::{
Expand All @@ -13,7 +14,13 @@ pub use self::{
mod fs;
mod redis;

type BoxError = Box<dyn Error + Send + Sync>;
#[inline]
fn get_bucket<'a>(
ctx: &'a crate::ctx::Context,
rep: &Resource<keyvalue::Bucket>,
) -> &'a BucketBackendDispatch {
&ctx.kv_ctx.buckets[rep.rep() as usize]
}

pub trait Backend {
type Bucket: BucketBackend;
Expand All @@ -22,16 +29,16 @@ pub trait Backend {
&self,
module_name: &str,
name: &str,
) -> impl Future<Output = Result<Self::Bucket, BoxError>> + Send;
) -> impl Future<Output = eyre::Result<Self::Bucket>> + Send;
}

#[enum_dispatch]
#[allow(async_fn_in_trait)]
pub trait BucketBackend {
async fn exists(&self, key: &str) -> Result<bool, BoxError>;
async fn delete(&self, key: &str) -> Result<(), BoxError>;
async fn get(&self, key: &str) -> Result<Option<Vec<u8>>, BoxError>;
async fn set(&self, key: &str, value: &[u8]) -> Result<(), BoxError>;
async fn exists(&self, key: &str) -> eyre::Result<bool>;
async fn delete(&self, key: &str) -> eyre::Result<()>;
async fn get(&self, key: &str) -> eyre::Result<Option<Vec<u8>>>;
async fn set(&self, key: &str, value: &[u8]) -> eyre::Result<()>;
}

#[derive(From)]
Expand All @@ -43,7 +50,7 @@ pub enum BackendDispatch {
impl Backend for BackendDispatch {
type Bucket = BucketBackendDispatch;

async fn open(&self, module_name: &str, name: &str) -> Result<Self::Bucket, BoxError> {
async fn open(&self, module_name: &str, name: &str) -> eyre::Result<Self::Bucket> {
match self {
Self::Fs(fs) => fs.open(module_name, name).await.map(Into::into),
Self::Redis(redis) => redis.open(module_name, name).await.map(Into::into),
Expand All @@ -59,10 +66,10 @@ pub enum BucketBackendDispatch {

#[async_trait]
impl keyvalue::HostBucket for crate::ctx::Context {
async fn open_bucket(
async fn open(
&mut self,
name: String,
) -> wasmtime::Result<Result<Resource<keyvalue::Bucket>, Resource<keyvalue::Error>>> {
) -> Result<Resource<keyvalue::Bucket>, Resource<keyvalue::Error>> {
let module_name = self
.kv_ctx
.module_name
Expand All @@ -72,41 +79,25 @@ impl keyvalue::HostBucket for crate::ctx::Context {
let bucket = match self.kv_ctx.storage.open(&name, module_name).await {
Ok(bucket) => bucket,
Err(error) => {
error!(?error, "failed to open bucket");
return Ok(Err(Resource::new_own(0)));
error!(?error, %module_name, %name, "failed to open bucket");
return Err(Resource::new_own(0));
}
};

let idx = self.kv_ctx.buckets.insert(bucket);
Ok(Ok(Resource::new_own(idx as u32)))
}

fn drop(&mut self, rep: Resource<keyvalue::Bucket>) -> wasmtime::Result<()> {
self.kv_ctx.buckets.remove(rep.rep() as usize);
Ok(())
Ok(Resource::new_own(idx as u32))
}
}

#[async_trait]
impl keyvalue::HostError for crate::ctx::Context {
fn drop(&mut self, _rep: Resource<keyvalue::Error>) -> wasmtime::Result<()> {
Ok(())
}
}

#[async_trait]
impl keyvalue::Host for crate::ctx::Context {
async fn get(
&mut self,
bucket: Resource<keyvalue::Bucket>,
key: String,
) -> wasmtime::Result<Result<Option<Vec<u8>>, Resource<keyvalue::Error>>> {
let bucket = &self.kv_ctx.buckets[bucket.rep() as usize];
match bucket.get(&key).await {
Ok(val) => Ok(Ok(val)),
) -> Result<Option<Vec<u8>>, Resource<keyvalue::Error>> {
match get_bucket(self, &bucket).get(&key).await {
Ok(value) => Ok(value),
Err(error) => {
error!(?error, %key, "failed to get key from storage");
Ok(Err(Resource::new_own(0)))
Err(Resource::new_own(0))
}
}
}
Expand All @@ -116,13 +107,12 @@ impl keyvalue::Host for crate::ctx::Context {
bucket: Resource<keyvalue::Bucket>,
key: String,
value: Vec<u8>,
) -> wasmtime::Result<Result<(), Resource<keyvalue::Error>>> {
let bucket = &self.kv_ctx.buckets[bucket.rep() as usize];
match bucket.set(&key, &value).await {
Ok(()) => Ok(Ok(())),
) -> Result<(), Resource<keyvalue::Error>> {
match get_bucket(self, &bucket).set(&key, &value).await {
Ok(value) => Ok(value),
Err(error) => {
error!(?error, %key, "failed to set key in storage");
Ok(Err(Resource::new_own(0)))
Err(Resource::new_own(0))
}
}
}
Expand All @@ -131,13 +121,12 @@ impl keyvalue::Host for crate::ctx::Context {
&mut self,
bucket: Resource<keyvalue::Bucket>,
key: String,
) -> wasmtime::Result<Result<(), Resource<keyvalue::Error>>> {
let bucket = &self.kv_ctx.buckets[bucket.rep() as usize];
match bucket.delete(&key).await {
Ok(()) => Ok(Ok(())),
) -> Result<(), Resource<keyvalue::Error>> {
match get_bucket(self, &bucket).delete(&key).await {
Ok(value) => Ok(value),
Err(error) => {
error!(?error, %key, "failed to delete key from storage");
Ok(Err(Resource::new_own(0)))
Err(Resource::new_own(0))
}
}
}
Expand All @@ -146,14 +135,28 @@ impl keyvalue::Host for crate::ctx::Context {
&mut self,
bucket: Resource<keyvalue::Bucket>,
key: String,
) -> wasmtime::Result<Result<bool, Resource<keyvalue::Error>>> {
let bucket = &self.kv_ctx.buckets[bucket.rep() as usize];
match bucket.exists(&key).await {
Ok(exists) => Ok(Ok(exists)),
) -> Result<bool, Resource<keyvalue::Error>> {
match get_bucket(self, &bucket).exists(&key).await {
Ok(value) => Ok(value),
Err(error) => {
error!(?error, %key, "failed to check existence of key in storage");
Ok(Err(Resource::new_own(0)))
Err(Resource::new_own(0))
}
}
}

fn drop(&mut self, rep: Resource<keyvalue::Bucket>) -> wasmtime::Result<()> {
self.kv_ctx.buckets.remove(rep.rep() as usize);
Ok(())
}
}

#[async_trait]
impl keyvalue::HostError for crate::ctx::Context {
fn drop(&mut self, _rep: Resource<keyvalue::Error>) -> wasmtime::Result<()> {
Ok(())
}
}

#[async_trait]
impl keyvalue::Host for crate::ctx::Context {}
12 changes: 6 additions & 6 deletions crates/kitsune-wasm-mrf/src/kv_storage/redis.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::BoxError;
use color_eyre::eyre;
use fred::{clients::RedisPool, interfaces::HashesInterface};
use kitsune_derive::typed_builder::TypedBuilder;

Expand All @@ -12,7 +12,7 @@ pub struct RedisBackend {
impl super::Backend for RedisBackend {
type Bucket = RedisBucketBackend;

async fn open(&self, module_name: &str, name: &str) -> Result<Self::Bucket, BoxError> {
async fn open(&self, module_name: &str, name: &str) -> eyre::Result<Self::Bucket> {
Ok(RedisBucketBackend {
name: format!("{REDIS_NAMESPACE}:{module_name}:{name}"),
pool: self.pool.clone(),
Expand All @@ -26,19 +26,19 @@ pub struct RedisBucketBackend {
}

impl super::BucketBackend for RedisBucketBackend {
async fn exists(&self, key: &str) -> Result<bool, BoxError> {
async fn exists(&self, key: &str) -> eyre::Result<bool> {
self.pool.hexists(&self.name, key).await.map_err(Into::into)
}

async fn delete(&self, key: &str) -> Result<(), BoxError> {
async fn delete(&self, key: &str) -> eyre::Result<()> {
self.pool.hdel(&self.name, key).await.map_err(Into::into)
}

async fn get(&self, key: &str) -> Result<Option<Vec<u8>>, BoxError> {
async fn get(&self, key: &str) -> eyre::Result<Option<Vec<u8>>> {
self.pool.hget(&self.name, key).await.map_err(Into::into)
}

async fn set(&self, key: &str, value: &[u8]) -> Result<(), BoxError> {
async fn set(&self, key: &str, value: &[u8]) -> eyre::Result<()> {
self.pool
.hset(&self.name, (key, value))
.await
Expand Down
9 changes: 1 addition & 8 deletions crates/kitsune-wasm-mrf/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,7 @@ macro_rules! event_dispatch {

#[async_trait]
impl logging::Host for crate::ctx::Context {
async fn log(
&mut self,
level: Level,
context: String,
message: String,
) -> wasmtime::Result<()> {
async fn log(&mut self, level: Level, context: String, message: String) {
event_dispatch!(level, context, message, {
Level::Trace => tracing::Level::TRACE,
Level::Debug => tracing::Level::DEBUG,
Expand All @@ -29,7 +24,5 @@ impl logging::Host for crate::ctx::Context {
Level::Error => tracing::Level::ERROR,
Level::Critical => tracing::Level::ERROR,
});

Ok(())
}
}
Binary file modified crates/kitsune-wasm-mrf/tests/example_mrf.component.wasm
Binary file not shown.
24 changes: 12 additions & 12 deletions crates/kitsune-wasm-mrf/wit/mrf.wit
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ interface keyvalue {
/// Logical collection of Key-Value pairs
resource bucket {
/// Open or create a new bucket
open-bucket: static func(name: string) -> result<bucket, error>;
}
open: static func(name: string) -> result<bucket, error>;

/// Get a value from a bucket
get: func(bucket: borrow<bucket>, key: string) -> result<option<list<u8>>, error>;
/// Get a value from a bucket
get: func(key: string) -> result<option<list<u8>>, error>;

/// Set the value inside a bucket
///
/// Overwrites existing values
set: func(bucket: borrow<bucket>, key: string, value: list<u8>) -> result<_, error>;
/// Set the value inside a bucket
///
/// Overwrites existing values silently
set: func(key: string, value: list<u8>) -> result<_, error>;

/// Delete the value from a bucket
delete: func(bucket: borrow<bucket>, key: string) -> result<_, error>;
/// Delete the value from a bucket
delete: func(key: string) -> result<_, error>;

/// Check if a key exists in the bucket
exists: func(bucket: borrow<bucket>, key: string) -> result<bool, error>;
/// Check if a key exists in the bucket
exists: func(key: string) -> result<bool, error>;
}
}

interface types {
Expand Down
6 changes: 3 additions & 3 deletions lib/mrf-manifest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ semver = { version = "1.0.23", features = ["serde"] }
serde = { version = "1.0.202", features = ["derive"] }
serde_json = { version = "1.0.117", optional = true }
thiserror = { version = "1.0.61", optional = true }
wasm-encoder = { version = "0.208.0", optional = true }
wasmparser = { version = "0.208.0", optional = true }
wasm-encoder = { version = "0.208.1", optional = true }
wasmparser = { version = "0.208.1", optional = true }

[dev-dependencies]
serde_json = "1.0.117"
insta = { version = "1.39.0", default-features = false, features = ["json"] }
wat = "1.208.0"
wat = "1.208.1"

[features]
decode = ["dep:leb128", "dep:serde_json", "dep:thiserror", "dep:wasmparser"]
Expand Down
Loading

0 comments on commit c4604a7

Please sign in to comment.