Description
Summary
With #4821, I provided a nice error library with stacktrace support for cosmos-sdk. This addressed #4708 to allow developers to get stack traces on test failures, if they use the new errors.
However, once we hit the Handler interface, we can no longer use the error interface, but rather fit it into a sdk.Result: type Handler func(ctx Context, msg Msg) Result
. This encourages many functions to return sdk.Error
, then return err.Result()
at the Handler interface. Which discourages use of richer error structs.
Problem Definition
Passing a consistent, stacktrace-enriched error class allows much better test-ability at all layers, especially at Handler-level or app-level integration tests. Let's make these errors first class citizens.
I have discussed this with @marbar3778 and he liked these changes. I would like to get more opinion from the other devs. I am happy for feedback here early on, and if you like the goal, but want a smoother migration path, I can provide a proposal for backwards compatibility here as well.
Proposal
I propose a few steps, some breaking, some non-breaking.
-
Add
sdk.ResultFromError(err error)
. Iferr
implementssdk.Error
, then we call theResult
method on it. If not, then we calltypes/errors.ABCIInfo()
to get the info and generate ansdk.Result
from that. We can standardize on this usage, and allow an incremental migration from existing error package -
Change
type Handler func(ctx Context, msg Msg) Result
totype Handler func(ctx Context, msg Msg) (*Result, error)
. And removeCode
andCodespace
fromResult
. Result should only be returned on success, error on failure.runTx
/runMsg
inBaseApp
can construct an ABCIResult properly on success or failure. In practice, this may be done in multiple steps to be less breaking, but should be after v0.36 in any case. (Note that we can still use sdk.Error and just return it without.Result()
as a first step, only changing the error creation piece by piece through the modules that desire it)
Advantages:
- Pass go
error
interface not ABCI-likeResult
struct to allow stacktrace info to flow over all levels of the code - Allow go-standard error checking rather than sdk-specific code
- Encourage go-standard extensions using
(*Result error)
design rather than returningsdk.Result
orsdk.Error
down into the Keeper and below.
Current:
res := h.keeper.DoStuff()
if !res.IsOK() {
return res
}
Proposed:
res, err := h.keeper.DoStuff()
if err != nil {
return nil, err
}
For Admin Use
- Not duplicate issue
- Appropriate labels applied
- Appropriate contributors tagged
- Contributor assigned/self-assigned
Activity