I have been porting deeply embedded software components to wasm components for some time and ran into an interesting restriction:
You can't implement interval timer, e.g. create-interval: func(interval-ns: u64) -> stream<> (stream of void/unit) in a separate component. Because the function can't spawn a thread running in the background and return the reading end of the stream back to the caller. The spawned thread becomes invalid once the function returns. (You can probably add a long running init: async func() which works around this, but it feels less elegant)
You can implement this functionality on the host. Moving the interval implementation into the guest component is not an option for me because I want to be able to implement it in a different way for different environments and I want to symbolically analyze a component to learn about the interval it wants to get called.
Short question: I vaguely recall interval timers (monotonous clock) had been part of 0.1 (?), should they be added to WASI 0.3 or is there a way to make the composition work again?
AI summary of the situation:
PastedText.txt
Christof Petig said:
Because the function can't spawn a thread running in the background and return the reading end of the stream back to the caller. The spawned thread becomes invalid once the function returns.
An async-lifted export can continue running as long as it wants after returning a stream; no need to spawn any threads, just call task.return to return the stream then keep running, only returning CALLBACK_CODE_EXIT from the callback function once the post-return work is complete. Or, in this case, never return CALLBACK_CODE_EXIT if the stream is meant to be infinite.
Cool, but I guess this requires a modified Rust binding, right?
The way you do it in Rust with wit-bindgen is by using spawn_local to queue up work to be done post-return.
Here's an example (which uses the old name spawn; I haven't updated it to use the latest wit-bindgen where the name is spawn_local): https://github.com/dicej/hello-wasip3-http/blob/cd2c4f4dcc2e1a9593c6769a21c9c6d3b0dee448/src/lib.rs#L27-L43
in fact, you must use spawn_local to return a wasi:http response with a body in Rust (or else bypass wit-bindgen entirely), since that's the only way to write to the stream that the response wraps
I will try it again, this is good news!
Last updated: Jul 29 2026 at 05:03 UTC