Discard state changes from update call without trap

Is there any way to discard memory from an update call without experiencing a trap? I would love to have that capability. My use case is within Sudograph. There are many possible errors that could occur within a GraphQL mutation (handled by an update call). I am using Rust, so I would love to propagate Results all the way to the exposed canister function from within my GraphQL/database code. I would still like to return a well-formatted GraphQL response detailing the errors, but I would also like to discard all of the memory. This is very important for transaction-like behavior (within a single canister at least).

I’m not sure if this is possible currently, and I think in Rust I have to experience a panic to experience a trap and thus to discard state changes. Panics and traps don’t let me give the user a nice JSON result. I imagine this would function very similarly to a query call, where state changes occur but are simply discarded.

@nomeata actually proposed such a mechanism in the past but it wasn’t adopted at the time.

FWIW, an ic0.trap can actually have some binary data attached, so you could pass back some json, but I’m not sure how much…

2 Likes

That would be a gross abuse of the API. The message passed to ic0.trap is meant to be text (not enforced, because it’s trapping already, but an implementation may just drop the data if it isn’t valid text), and definitely not used for programmatic consumption. Not that I can stop anyone, of course …

It seems like the system lacks this mechanism (unless you feel like abusing the API in a “gross” way, which could be fun, but probably not reliable for the future.)

I wonder what Rust as a language provides for doing a kind of speculative mutation to state? (“transactions”?)

In Motoko, I’d advise a developer to use applicative data structures for their updates, and get the rollback semantics of a transaction failure from the applicative (purely functional) nature of the “updates”. The final mutation would only happen in the #ok case. Perhaps something similar could be done in Rust?

This crate always seemed intriguing to me, though I haven’t used it myself, yet.

2 Likes