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  }