Stream: wasm

Topic: Implementing Async Functions in WebAssembly Modules (Rust)


view this post on Zulip Utilize3214 (Dec 11 2024 at 06:45):

Current Setup

I have several WebAssembly modules written in Rust using synchronous code. Here's how they're currently structured:

mod bindings;
pub use bindings::{Guest, Object, Value};

pub struct Extract;

impl Guest for Extract {
    fn query(args: Vec<(String, Value)>) -> Result<Object, String> {
        let result: Vec<Vec<(String, String)>> = Vec::new();
        // do something
        Ok(result)
    }
}

bindings::export!(Extract with_types_in bindings);

Questions About Async Implementation

  1. Module Side: How should I modify the WASM module to support async functions?

  2. Host Side: I'm using wasmtime in Rust to call these modules. Current calling pattern:
    rust f.call(&self, mut store: impl AsContextMut, params: &[Val], results: &mut [Val])

  3. Mixed Async/Sync Environment:

Has anyone implemented something similar or can point me in the right direction?

view this post on Zulip raskyld (Dec 11 2024 at 09:04):

I have implemented an async executor for WebAssembly in the context of: https://wasmcloud.com/blog/2024-12-10-leptos-and-wasi-0.2-for-full-stack-wasm-development

Basically, my implementation makes any pollable awaitable like that:

WasiPoll::new(your_pollable).await

So if you somehow can make your host return a pollable, it should do but I don't know if it's something easy to do with Wasmtime. I will let expert answer on this one!

The code is there: https://github.com/leptos-rs/leptos_wasi/blob/main/src/executor.rs

wasmCloud contributor and Leptos WASI author Enzo Nocera shares how Rust's Leptos web framework implemented WASI 0.2 support.
Leptos WASI Preview 2 integration, working with wasmcloud and possibly others - leptos-rs/leptos_wasi

view this post on Zulip raskyld (Dec 11 2024 at 09:05):

I have been thinking about porting the implementation to a standalone crate as well but IDK how useful it would be

view this post on Zulip Christof Petig (Dec 15 2024 at 11:44):

Utilize3214 said:

Has anyone implemented something similar or can point me in the right direction?

Take a look at Joel's WASI 0.3 prototype at https://github.com/dicej/component-async-demo - I believe this is the most advanced way of combining sync and async. Also Luke's talk "stream of conscious on the future of components" explains its concepts pretty well.

Demo of async support for wit-bindgen, wasm-tools, and wasmtime - dicej/component-async-demo

view this post on Zulip Christof Petig (Dec 16 2024 at 12:49):

Here is the link to Luke's talk YouTube - - YouTube

view this post on Zulip Joel Dice (Dec 16 2024 at 14:42):

FYI, that component-async-demo repo is based on forks of wasm-tools, wit-bindgen, and wasmtime, and the wasmtime one in particular is not yet ready for serious use. I'm working to get all those forks merged upstream, but until that's done you should consider the code experimental. And even after everything's merged, the async parts will be gated behind a Cargo feature that's disabled by default, so you should _still_ consider it experimental until that feature is enabled by default.

Meanwhile, there are several WASIp2-compatible async runtimes/executors out there besides the one @raskyld mentioned, e.g. https://crates.io/crates/wasi-async-runtime and https://crates.io/crates/spin-executor. You could even write your own without a lot of trouble.


Last updated: Dec 23 2024 at 12:05 UTC