Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add wasi:keyvalue examples #208

Merged
merged 7 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
238 changes: 69 additions & 169 deletions Cargo.lock

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wrpc"
version = "0.4.0"
version = "0.5.0"
description = "WebAssembly component-native RPC framework based on WIT"

authors.workspace = true
Expand Down Expand Up @@ -123,23 +123,23 @@ tracing = { version = "0.1", default-features = false }
tracing-subscriber = { version = "0.3", default-features = false }
uuid = { version = "1", default-features = false }
url = { version = "2", default-features = false }
wasi-preview1-component-adapter-provider = { version = "23.0.1", default-features = false }
wasm-tokio = { version = "0.5.16", default-features = false }
wasmcloud-component-adapters = { version = "0.11", default-features = false }
wasmparser = { version = "0.214", default-features = false }
wasmtime = { version = "22", default-features = false }
wasmtime-wasi = { version = "22", default-features = false }
wit-bindgen = { version = "0.28", default-features = false }
wit-bindgen-core = { version = "0.28", default-features = false }
wit-bindgen-wrpc = { version = "0.4.13", default-features = false, path = "./crates/wit-bindgen" }
wit-bindgen-wrpc-go = { version = "0.2", default-features = false, path = "./crates/wit-bindgen-go" }
wit-bindgen-wrpc-rust = { version = "0.4.13", default-features = false, path = "./crates/wit-bindgen-rust" }
wit-bindgen-wrpc-rust-macro = { version = "0.4.13", default-features = false, path = "./crates/wit-bindgen-rust-macro" }
wit-bindgen-wrpc = { version = "0.5", default-features = false, path = "./crates/wit-bindgen" }
wit-bindgen-wrpc-go = { version = "0.3", default-features = false, path = "./crates/wit-bindgen-go" }
wit-bindgen-wrpc-rust = { version = "0.5", default-features = false, path = "./crates/wit-bindgen-rust" }
wit-bindgen-wrpc-rust-macro = { version = "0.5", default-features = false, path = "./crates/wit-bindgen-rust-macro" }
wit-component = { version = "0.214", default-features = false }
wit-parser = { version = "0.214", default-features = false }
wrpc-cli = { version = "0.2.1", path = "./crates/cli", default-features = false }
wrpc-introspect = { version = "0.1.1", default-features = false, path = "./crates/introspect" }
wrpc-introspect = { version = "0.2", default-features = false, path = "./crates/introspect" }
wrpc-runtime-wasmtime = { version = "0.19.4", path = "./crates/runtime-wasmtime", default-features = false }
wrpc-transport = { version = "0.26.7", path = "./crates/transport", default-features = false }
wrpc-transport-nats = { version = "0.22.3", path = "./crates/transport-nats", default-features = false }
wrpc-transport-quic = { version = "0.1.1", path = "./crates/transport-quic", default-features = false }
wrpc-wasmtime-nats-cli = { version = "0.3.4", path = "./crates/wasmtime-nats-cli", default-features = false }
wrpc-wasmtime-nats-cli = { version = "0.4.0", path = "./crates/wasmtime-nats-cli", default-features = false }
2 changes: 1 addition & 1 deletion crates/introspect/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wrpc-introspect"
version = "0.1.1"
version = "0.2.0"
description = "Component type introspection for wRPC"

authors.workspace = true
Expand Down
5 changes: 4 additions & 1 deletion crates/introspect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ pub fn rpc_func_name(func: &Function) -> &str {
.name
.strip_prefix("[static]")
.expect("failed to strip `[static]` prefix"),
FunctionKind::Method(..) => func.item_name(),
FunctionKind::Method(..) => func
.name
.strip_prefix("[method]")
.expect("failed to strip `[method]` prefix"),
FunctionKind::Freestanding => &func.name,
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/transport/src/invoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ pub trait InvokeExt: Invoke {
}

/// Returns a [`Timeout`], wrapping [Self] with an implementation of [Invoke], which will
/// error, if call to [Self::invoke] does not return within a supplied `timeout`
/// error, if call to [`Self::invoke`] does not return within a supplied `timeout`
fn timeout(&self, timeout: Duration) -> Timeout<'_, Self> {
Timeout {
inner: self,
Expand Down
29 changes: 29 additions & 0 deletions crates/transport/src/value.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use core::any::TypeId;
use core::fmt::{self, Debug};
use core::future::Future;
use core::hash::{Hash, Hasher};
use core::iter::zip;
use core::marker::PhantomData;
use core::mem;
Expand Down Expand Up @@ -61,6 +62,20 @@ impl<T: ?Sized> From<ResourceBorrow<T>> for Bytes {
}
}

impl<T: ?Sized> PartialEq for ResourceBorrow<T> {
fn eq(&self, other: &Self) -> bool {
self.repr == other.repr
}
}

impl<T: ?Sized> Eq for ResourceBorrow<T> {}

impl<T: ?Sized> Hash for ResourceBorrow<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.repr.hash(state)
}
}

impl<T: ?Sized> AsRef<[u8]> for ResourceBorrow<T> {
fn as_ref(&self) -> &[u8] {
&self.repr
Expand Down Expand Up @@ -124,6 +139,20 @@ impl<T: ?Sized> From<ResourceOwn<T>> for Bytes {
}
}

impl<T: ?Sized> PartialEq for ResourceOwn<T> {
fn eq(&self, other: &Self) -> bool {
self.repr == other.repr
}
}

impl<T: ?Sized> Eq for ResourceOwn<T> {}

impl<T: ?Sized> Hash for ResourceOwn<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.repr.hash(state)
}
}

impl<T: ?Sized> AsRef<[u8]> for ResourceOwn<T> {
fn as_ref(&self) -> &[u8] {
&self.repr
Expand Down
4 changes: 2 additions & 2 deletions crates/wasmtime-nats-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wrpc-wasmtime-nats-cli"
version = "0.3.4"
version = "0.4.0"
description = "wRPC Wasmtime NATS CLI"

authors.workspace = true
Expand Down Expand Up @@ -34,7 +34,7 @@ tracing-subscriber = { workspace = true, features = [
"fmt",
] }
url = { workspace = true }
wasmcloud-component-adapters = { workspace = true }
wasi-preview1-component-adapter-provider = { workspace = true }
wasmparser = { workspace = true }
wasmtime = { workspace = true, features = [
"addr2line",
Expand Down
11 changes: 6 additions & 5 deletions crates/wasmtime-nats-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ use tokio::sync::Mutex;
use tokio::task::JoinSet;
use tracing::{error, info, instrument, warn, Instrument as _, Span};
use url::Url;
use wasmcloud_component_adapters::{
WASI_PREVIEW1_COMMAND_COMPONENT_ADAPTER, WASI_PREVIEW1_REACTOR_COMPONENT_ADAPTER,
use wasi_preview1_component_adapter_provider::{
WASI_SNAPSHOT_PREVIEW1_ADAPTER_NAME, WASI_SNAPSHOT_PREVIEW1_COMMAND_ADAPTER,
WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER,
};
use wasmtime::component::{types, Component, InstancePre, Linker, ResourceType};
use wasmtime::{Engine, Store};
Expand Down Expand Up @@ -166,7 +167,7 @@ where
.validate(true)
.module(&wasm)
.context("failed to set core component module")?
.adapter("wasi_snapshot_preview1", adapter)
.adapter(WASI_SNAPSHOT_PREVIEW1_ADAPTER_NAME, adapter)
.context("failed to add WASI adapter")?
.encode()
.context("failed to encode a component")?
Expand Down Expand Up @@ -271,7 +272,7 @@ pub async fn handle_run(
.context("failed to connect to NATS")?;

let (pre, engine, _) =
instantiate_pre(WASI_PREVIEW1_COMMAND_COMPONENT_ADAPTER, None, workload).await?;
instantiate_pre(WASI_SNAPSHOT_PREVIEW1_COMMAND_ADAPTER, None, workload).await?;
let mut store = new_store(
&engine,
wrpc_transport_nats::Client::new(nats, target, None),
Expand Down Expand Up @@ -587,7 +588,7 @@ pub async fn handle_serve(
let nats = Arc::new(nats);

let (pre, engine, guest_resources) =
instantiate_pre(WASI_PREVIEW1_REACTOR_COMPONENT_ADAPTER, None, workload).await?;
instantiate_pre(WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER, None, workload).await?;

let clt = wrpc_transport_nats::Client::new(Arc::clone(&nats), target, None);
let srv = wrpc_transport_nats::Client::new(nats, prefix, group.map(Arc::from));
Expand Down
2 changes: 1 addition & 1 deletion crates/wit-bindgen-go/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wit-bindgen-wrpc-go"
version = "0.2.1"
version = "0.3.0"
description = """
Go bindings generator for wRPC
"""
Expand Down
2 changes: 1 addition & 1 deletion crates/wit-bindgen-go/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2746,7 +2746,7 @@ impl InterfaceGenerator<'_> {
",
);
for (i, func) in methods[&id].iter().enumerate() {
let name = &func.item_name();
let name = rpc_func_name(func);
uwriteln!(
self.src,
r#"stop{i}, err := s.Serve(rx, "{name}", func(ctx {context}.Context, w {wrpc}.IndexWriter, r {wrpc}.IndexReadCloser) error {{"#,
Expand Down
2 changes: 1 addition & 1 deletion crates/wit-bindgen-rust-macro/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wit-bindgen-wrpc-rust-macro"
version = "0.4.13"
version = "0.5.0"
description = """
Procedural macro paired with the `wit-bindgen-wrpc` crate.
"""
Expand Down
2 changes: 1 addition & 1 deletion crates/wit-bindgen-rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wit-bindgen-wrpc-rust"
version = "0.4.13"
version = "0.5.0"
description = """
Rust bindings generator for wRPC, typically used through
the `wit-bindgen-wrpc` crate's `generate!` macro.
Expand Down
4 changes: 2 additions & 2 deletions crates/wit-bindgen-rust/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ pub fn serve_interface<'a, T: {wrpc_transport}::Serve>(
self.src,
r#"
let wrpc__ = {anyhow}::Context::context(
{wrpc_transport}::SendFuture::send({wrpc_transport}::InvokeExt::invoke_values_blocking(wrpc__, cx__, "{instance}", "{}", ({params}), "#,
{wrpc_transport}::SendFuture::send({wrpc_transport}::InvokeExt::invoke_values_blocking(wrpc__, cx__, "{instance}", "{}", ({params}), "#,
rpc_func_name(func),
wrpc_transport = self.gen.wrpc_transport_path(),
params = {
Expand Down Expand Up @@ -660,7 +660,7 @@ pub fn serve_interface<'a, T: {wrpc_transport}::Serve>(
self.src,
r#"
let (wrpc__, io__) = {anyhow}::Context::context(
{wrpc_transport}::SendFuture::send({wrpc_transport}::InvokeExt::invoke_values(wrpc__, cx__, "{instance}", "{}", ({params}), "#,
{wrpc_transport}::SendFuture::send({wrpc_transport}::InvokeExt::invoke_values(wrpc__, cx__, "{instance}", "{}", ({params}), "#,
rpc_func_name(func),
wrpc_transport = self.gen.wrpc_transport_path(),
params = {
Expand Down
2 changes: 1 addition & 1 deletion crates/wit-bindgen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wit-bindgen-wrpc"
version = "0.4.13"
version = "0.5.0"
description = """
Rust bindings generator for wRPC.
"""
Expand Down
1 change: 0 additions & 1 deletion examples/rust/complex-component-client/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::bindings::wrpc_examples::complex::resources;

#[allow(clippy::missing_safety_doc)]
mod bindings {
wit_bindgen::generate!({
with: {
Expand Down
4 changes: 2 additions & 2 deletions examples/rust/complex-component-server/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use bindings::exports::wrpc_examples::complex::resources::FooBorrow;

#[allow(clippy::missing_safety_doc)]
mod bindings {
use crate::Handler;
Expand All @@ -13,6 +11,8 @@ mod bindings {
export!(Handler);
}

use bindings::exports::wrpc_examples::complex::resources::FooBorrow;

pub struct Handler;

pub struct Foo;
Expand Down
1 change: 0 additions & 1 deletion examples/rust/wasi-keyvalue-component-client/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#[allow(clippy::missing_safety_doc)]
mod bindings {
wit_bindgen::generate!({
with: {
Expand Down
5 changes: 0 additions & 5 deletions examples/rust/wasi-keyvalue-component-client/wit/host.wit

This file was deleted.

5 changes: 5 additions & 0 deletions examples/rust/wasi-keyvalue-component-client/wit/world.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package wrpc-examples:wasi-keyvalue-component-client;

world client {
import wasi:keyvalue/store@0.2.0-draft;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
target = "wasm32-wasi"
16 changes: 16 additions & 0 deletions examples/rust/wasi-keyvalue-component-server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "wasi-keyvalue-component-server"
version = "0.1.0"

authors.workspace = true
categories.workspace = true
edition.workspace = true
homepage.workspace = true
license.workspace = true
repository.workspace = true

[lib]
crate-type = ["cdylib"]

[dependencies]
wit-bindgen = { workspace = true, features = ["realloc", "macros"] }
89 changes: 89 additions & 0 deletions examples/rust/wasi-keyvalue-component-server/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
mod bindings {
use crate::Handler;

wit_bindgen::generate!({
with: {
"wasi:keyvalue/store@0.2.0-draft": generate
}
});

export!(Handler);
}

use std::collections::HashMap;
use std::sync::{Arc, Mutex, OnceLock, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard};

use bindings::exports::wasi::keyvalue::store::{self, KeyResponse};

type Result<T> = core::result::Result<T, store::Error>;

pub struct Handler;

fn map_lock<'a, T, U>(
lock: &'a RwLock<T>,
f: impl FnOnce(&'a RwLock<T>) -> core::result::Result<U, PoisonError<U>>,
) -> Result<U> {
f(lock).map_err(|err| store::Error::Other(err.to_string()))
}

#[derive(Clone, Default)]
pub struct Bucket(Arc<RwLock<HashMap<String, Vec<u8>>>>);

impl Bucket {
fn read(&self) -> Result<RwLockReadGuard<'_, HashMap<String, Vec<u8>>>> {
map_lock(&self.0, RwLock::read)
}

fn write(&self) -> Result<RwLockWriteGuard<'_, HashMap<String, Vec<u8>>>> {
map_lock(&self.0, RwLock::write)
}
}

impl bindings::exports::wasi::keyvalue::store::GuestBucket for Bucket {
fn get(&self, key: String) -> Result<Option<Vec<u8>>> {
let bucket = self.read()?;
Ok(bucket.get(&key).cloned())
}

fn set(&self, key: String, value: Vec<u8>) -> Result<()> {
let mut bucket = self.write()?;
bucket.insert(key, value);
Ok(())
}

fn delete(&self, key: String) -> Result<()> {
let mut bucket = self.write()?;
bucket.remove(&key);
Ok(())
}

fn exists(&self, key: String) -> Result<bool> {
let bucket = self.read()?;
Ok(bucket.contains_key(&key))
}

fn list_keys(&self, cursor: Option<u64>) -> Result<KeyResponse> {
let bucket = self.read()?;
let bucket = bucket.keys();
let keys = if let Some(cursor) = cursor {
let cursor =
usize::try_from(cursor).map_err(|err| store::Error::Other(err.to_string()))?;
bucket.skip(cursor).cloned().collect()
} else {
bucket.cloned().collect()
};
Ok(KeyResponse { keys, cursor: None })
}
}

impl bindings::exports::wasi::keyvalue::store::Guest for Handler {
type Bucket = Bucket;

fn open(identifier: String) -> Result<store::Bucket> {
static STORE: OnceLock<Mutex<HashMap<String, Bucket>>> = OnceLock::new();
let store = STORE.get_or_init(Mutex::default);
let mut store = store.lock().expect("failed to lock store");
let bucket = store.entry(identifier).or_default().clone();
Ok(store::Bucket::new(bucket))
}
}
4 changes: 4 additions & 0 deletions examples/rust/wasi-keyvalue-component-server/wit/deps.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[keyvalue]
url = "https://github.com/WebAssembly/wasi-keyvalue/archive/main.tar.gz"
sha256 = "d2de617fe31ec0abc6072f75f97dd22bf95b3231d5b3111471d73871df9081cd"
sha512 = "6f0b4e44c684d760c54552e2bde9bc976e0a4f6525fc1d47acb98625e030847276436242f42a41f4da1bb9169fb2968c53d659d61af9b2f709f4eb6f9880e2c7"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
keyvalue = "https://github.com/WebAssembly/wasi-keyvalue/archive/main.tar.gz"
Loading
Loading