I would like to discus few failure scenarios around futures and streams.
let's assume function add: func(a: u8, b: u8) -> u8
;
I think that when you consume p3 method as async, the future/promise/Task you get could be rejected/failed by producer side and the caller will receive error-context
which they could handle, right ? This is nice.
A) I would like to understand what happens when producer component exports it as async, therefore fallible and consuming component imports it as synchronous, therefore un-fallible. What happens to consumer when the producer rejects the promise ? Is the consumer instance going to trap/abort ?
B) It could also happen that the implementation would be virtualized by wRPC, which would introduce failures (of networking) into this contract.
Easy answer would be to proclaim that we should always consume imports as async, when we know that it could be remote. This forces async "color" to your functions. It also introduces unexpected latency.
But that's not an answer for sync components that get dependencies remote-virtualized unknowingly.
I'm worried that in this way wRPC is introducing impedance mismatch in DCOM way.
cc @Luke Wagner @Joel Dice @Roman Volosatovs
My understanding is that error-context
is used with streams/futures but not tasks. Tasks themselves can only fail by returning an explicit error result
or trapping.
I was thinking C# Task
in text above as marshaled from future
. Sorry for confusion.
In context of wRPC, the bindgen generates a fallible signature (e.g. your add
function import would return anyhow::Result<u8>
)
If any async value is used in import in either parameter or result tuple, the bindgen will return an additional value - an I/O driver - a future, which must be polled - that future may fail (IIRC with std::io::Error
directly)
So, wRPC is not usable as virtualization of existing WIT ?
wRPC is a general-purpose RPC framework, it's not anyhow specific to WebAssembly. It is built on WIT though, so being able to use existing WIT is precisely the use case.
Not sure exactly what you're asking.
If we're talking about "polyfilling" Wasm component imports, then RPC protocol choice here seems pretty arbitrary and hiding fallible network I/O underneath it is a bad idea regardless of the RPC protocol chosen
Generally, you would want a local entity exporting an interface (a host plugin) and converting the transport layer errors into application layer ones
Roman Volosatovs said:
If we're talking about "polyfilling" Wasm component imports, then RPC protocol choice here seems pretty arbitrary and hiding fallible network I/O underneath it is a bad idea regardless of the RPC protocol chosen
Thank you for clarifying, I was not clear if this is/was the design intent. That solves my worry about B).
Is there separate wit-bindgen mode/version that is doing the wrapping as anyhow::Result<u8>
?
wRPC has a custom bindgen. There are also some optimizations in place for remote use cases
wRPC bindgen tries hard to match the API of wit-bindgen
, which is why wRPC repo merges from wit-bindgen
tree
I'm thinking that in languages which support exceptions, fallibility could be solved without changing the signature.
In rust, generating anyhow::Result<u8>
is also solution for problem A) ? Is that what it does in WASIp3 wit-bindgen ?
Last updated: Dec 23 2024 at 12:05 UTC