-
Notifications
You must be signed in to change notification settings - Fork 91
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
[Task] Implement a serializable error #321
Comments
There are two problems presented here:
Serializable errors are currently the most important as they prevent actor handlers implementing branching behaviour based on error types. To recap, the example pub enum Error {
#[error("Stronghold snapshot password not found")]
StrongholdPasswordNotSet,
#[error("Stronghold error: {0}")]
StrongholdResult(String),
#[error(transparent)]
IoError(#[from] std::io::Error),
#[error(transparent)]
StrongholdError(#[from] iota_stronghold::Error),
...
} Aside: we also want to avoid Considering just (de)serialization, we have several options. Option 1:
|
Motivation
The upcoming actor exchanges messages over the network, where errors can occur. The current error enums we use are not serializable, and thus cannot be exchanged between actors. Another motivation may be to improve the currently stringly-typed errors in the WebAssembly bindings. In order to pass a value to JavaScript, it needs to be serializable. Errors also need to be exposable to future bindings, which often involves (de)serialization.
Description
Implement an error type that is serializable for over-the-network and bindings usage. WebAssembly bindings are a good case study. We currently use error enums in Rust, but any bindings that use a C FFI as the common interface, such as Wasm, can only use C-style enums. We have talked about this a number of times, and I want to summarize the approaches we've discussed, as it is not entirely clear yet, which is the best.
The general idea is to use an error code approach, and we've discussed variants of it. As an example we consider a part of the account error enum.
The simplest approach would be to map each of the variants to some error code. For the variants that contain associated data, information will be lost (or preserved in stringified form). On the receiver side, the error cannot be reconstructed, since not all information is available. Furthermore, since no enum is defined, the receiver only has the bare number but has a hard time attaching a meaning to it.
Thus, to build on this approach, we define roughly this Rust code:
To convert the example variants into this Error, we might do:
StrongholdPasswordNotSet
variant is easily translated as some error code.StrongholdResult
has an associatedString
. We can translate the variant itself to some number, and additionally transmit the stringified error.IoError
is a fatal error from the other side, and the caller cannot do much about it, similar to a 5XX HTTP status. These errors can be mapped to a catch-allInternalError
(or similar) and also stringified to provide more detailed human-readable information. Some errors also should not be exposed, such asStrongholdMutexPoisoned
(not represented in the example above), which can similarly be mapped to the catch-all variant.StrongholdError
can either be mapped to a singleStrongholdError
error code, or each of its variants can be mapped to error codes. The former approach means the caller has less information available, i.e. cannot programmatically match on specific variants. It is at least mitigated by the stringified version in terms of human readability. The latter approach includes a lot more maintenance burden. One other idea was to use two integers. E.g. to mapStrongholdError
, we store its error code in the first integer, and use the second integer to store error code of the inner variant. This has very high maintenance costs. To convert two integers back into a nested enum, we would need to copy the entire first two levels of nesting of theError
enum introduced above into new serializable enums.There is perhaps more investigation needed to find the optimal approach. An implementation with unions might be viable, although given the
unsafe
ty they introduce and the conversion that would also be necessary, similar to the previous approach, makes this less desirable.Any feedback on this write-up is welcome!
Resources
To-do list
Create a task-specific to-do list . Please link PRs that match the To-do list item behind the item after it has been submitted.
identity_account::error::Error
and perhapsidentity_iota::error::Error
.Change checklist
Add an
x
to the boxes that are relevant to your changes, and delete any items that are not.The text was updated successfully, but these errors were encountered: