github.com/wfusion/gofusion@v1.1.14/common/infra/watermill/message/router/middleware/recoverer.go (about) 1 package middleware 2 3 import ( 4 "fmt" 5 "runtime/debug" 6 7 "github.com/pkg/errors" 8 "github.com/wfusion/gofusion/common/infra/watermill/message" 9 ) 10 11 // RecoveredPanicError holds the recovered panic's error along with the stacktrace. 12 type RecoveredPanicError struct { 13 V any 14 Stacktrace string 15 } 16 17 func (p RecoveredPanicError) Error() string { 18 return fmt.Sprintf("panic occurred: %#v, stacktrace: \n%s", p.V, p.Stacktrace) 19 } 20 21 // Recoverer recovers from any panic in the handler and appends RecoveredPanicError with the stacktrace 22 // to any error returned from the handler. 23 func Recoverer(h message.HandlerFunc) message.HandlerFunc { 24 return func(event *message.Message) (events []*message.Message, err error) { 25 panicked := true 26 27 defer func() { 28 if r := recover(); r != nil || panicked { 29 err = errors.WithStack(RecoveredPanicError{V: r, Stacktrace: string(debug.Stack())}) 30 } 31 }() 32 33 events, err = h(event) 34 panicked = false 35 return events, err 36 } 37 }