Create actor error type
License: MIT Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
This commit is contained in:
parent
978bd5c17e
commit
02dab3eb51
69
chain/actors/aerrors/error.go
Normal file
69
chain/actors/aerrors/error.go
Normal file
@ -0,0 +1,69 @@
|
||||
package aerrors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
func IsFatal(err ActorError) bool {
|
||||
return err != nil && err.IsFatal()
|
||||
}
|
||||
func RetCode(err ActorError) uint8 {
|
||||
if err == nil {
|
||||
return 0
|
||||
} else {
|
||||
return err.RetCode()
|
||||
}
|
||||
}
|
||||
|
||||
type internalActorError interface {
|
||||
ActorError
|
||||
FormatError(p xerrors.Printer) (next error)
|
||||
Unwrap() error
|
||||
}
|
||||
|
||||
type ActorError interface {
|
||||
error
|
||||
IsFatal() bool
|
||||
RetCode() uint8
|
||||
}
|
||||
|
||||
type actorError struct {
|
||||
fatal bool
|
||||
retCode uint8
|
||||
|
||||
msg string
|
||||
frame xerrors.Frame
|
||||
err error
|
||||
}
|
||||
|
||||
func (e *actorError) IsFatal() bool {
|
||||
return e.fatal
|
||||
}
|
||||
|
||||
func (e *actorError) RetCode() uint8 {
|
||||
return e.retCode
|
||||
}
|
||||
|
||||
func (e *actorError) Error() string {
|
||||
return fmt.Sprint(e)
|
||||
}
|
||||
func (e *actorError) Format(s fmt.State, v rune) { xerrors.FormatError(e, s, v) }
|
||||
func (e *actorError) FormatError(p xerrors.Printer) (next error) {
|
||||
p.Print(e.msg)
|
||||
if e.fatal {
|
||||
p.Print(" (FATAL)")
|
||||
} else {
|
||||
p.Printf(" (RetCode=%d)", e.retCode)
|
||||
}
|
||||
|
||||
e.frame.Format(p)
|
||||
return e.err
|
||||
}
|
||||
|
||||
func (e *actorError) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
var _ internalActorError = (*actorError)(nil)
|
35
chain/actors/aerrors/error_test.go
Normal file
35
chain/actors/aerrors/error_test.go
Normal file
@ -0,0 +1,35 @@
|
||||
package aerrors_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/filecoin-project/go-lotus/chain/actors/aerrors"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
func TestFatalError(t *testing.T) {
|
||||
e1 := xerrors.New("out of disk space")
|
||||
e2 := xerrors.Errorf("could not put node: %w", e1)
|
||||
e3 := xerrors.Errorf("could not save head: %w", e2)
|
||||
ae := Escalate(e3, "failed to save the head")
|
||||
aw1 := Wrap(ae, "saving head of new miner actor")
|
||||
aw2 := Absorb(aw1, 1, "try to absorb fatal error")
|
||||
aw3 := Wrap(aw2, "initializing actor")
|
||||
aw4 := Wrap(aw3, "creating miner in storage market")
|
||||
t.Logf("Verbose error: %+v", aw4)
|
||||
t.Logf("Normal error: %v", aw4)
|
||||
assert.True(t, IsFatal(aw4), "should be fatal")
|
||||
}
|
||||
func TestAbsorbeError(t *testing.T) {
|
||||
e1 := xerrors.New("EOF")
|
||||
e2 := xerrors.Errorf("could not decode: %w", e1)
|
||||
ae := Absorb(e2, 35, "failed to decode CBOR")
|
||||
aw1 := Wrap(ae, "saving head of new miner actor")
|
||||
aw2 := Wrap(aw1, "initializing actor")
|
||||
aw3 := Wrap(aw2, "creating miner in storage market")
|
||||
t.Logf("Verbose error: %+v", aw3)
|
||||
t.Logf("Normal error: %v", aw3)
|
||||
assert.Equal(t, uint8(35), RetCode(aw3))
|
||||
}
|
86
chain/actors/aerrors/wrap.go
Normal file
86
chain/actors/aerrors/wrap.go
Normal file
@ -0,0 +1,86 @@
|
||||
package aerrors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
func Wrap(err ActorError, message string) ActorError {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &actorError{
|
||||
fatal: IsFatal(err),
|
||||
retCode: RetCode(err),
|
||||
|
||||
msg: message,
|
||||
frame: xerrors.Caller(1),
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap extens chain of errors with
|
||||
func Wrapf(err ActorError, format string, args ...interface{}) ActorError {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &actorError{
|
||||
fatal: IsFatal(err),
|
||||
retCode: RetCode(err),
|
||||
|
||||
msg: fmt.Sprintf(format, args...),
|
||||
frame: xerrors.Caller(1),
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// Absorb takes and error and makes in not fatal ActorError
|
||||
func Absorb(err error, retCode uint8, msg string) ActorError {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if aerr, ok := err.(ActorError); ok && IsFatal(aerr) {
|
||||
return &actorError{
|
||||
fatal: true,
|
||||
retCode: 0,
|
||||
|
||||
msg: "tried absorbing an error that is alreay an fatal error",
|
||||
frame: xerrors.Caller(1),
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
if retCode == 0 {
|
||||
return &actorError{
|
||||
fatal: true,
|
||||
retCode: 0,
|
||||
|
||||
msg: "tried absorbing an error and setting RetCode to 0",
|
||||
frame: xerrors.Caller(1),
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
return &actorError{
|
||||
fatal: false,
|
||||
retCode: retCode,
|
||||
|
||||
msg: msg,
|
||||
frame: xerrors.Caller(1),
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// Escalate takes and error and escalates it into a fatal error
|
||||
func Escalate(err error, msg string) ActorError {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &actorError{
|
||||
fatal: true,
|
||||
|
||||
msg: msg,
|
||||
frame: xerrors.Caller(1),
|
||||
err: err,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user