github.com/Jeffail/benthos/v3@v3.65.0/internal/batch/error.go (about) 1 // Package batch contains internal utilities for interacting with message 2 // batches. 3 package batch 4 5 import ( 6 "errors" 7 8 "github.com/Jeffail/benthos/v3/lib/types" 9 ) 10 11 // Error is an error type that also allows storing granular errors for each 12 // message of a batch. 13 type Error struct { 14 err error 15 source types.Message 16 partErrors map[int]error 17 } 18 19 // NewError creates a new batch-wide error, where it's possible to add granular 20 // errors for individual messages of the batch. 21 func NewError(msg types.Message, err error) *Error { 22 if berr, ok := err.(*Error); ok { 23 err = berr.Unwrap() 24 } 25 return &Error{ 26 err: err, 27 source: msg, 28 } 29 } 30 31 // Failed stores an error state for a particular message of a batch. Returns a 32 // pointer to the underlying error, allowing with method to be chained. 33 // 34 // If Failed is not called then all messages are assumed to have failed. If it 35 // is called at least once then all message indexes that aren't explicitly 36 // failed are assumed to have been processed successfully. 37 func (e *Error) Failed(i int, err error) *Error { 38 if e.partErrors == nil { 39 e.partErrors = make(map[int]error) 40 } 41 e.partErrors[i] = err 42 return e 43 } 44 45 // IndexedErrors returns the number of indexed errors that have been registered 46 // for the batch. 47 func (e *Error) IndexedErrors() int { 48 return len(e.partErrors) 49 } 50 51 // WalkableError is an interface implemented by batch errors that allows you to 52 // walk the messages of the batch and dig into the individual errors. 53 type WalkableError interface { 54 WalkParts(fn func(int, types.Part, error) bool) 55 IndexedErrors() int 56 error 57 } 58 59 // WalkParts applies a closure to each message that was part of the request that 60 // caused this error. The closure is provided the message part index, a pointer 61 // to the part, and its individual error, which may be nil if the message itself 62 // was processed successfully. The closure returns a bool which indicates 63 // whether the iteration should be continued. 64 func (e *Error) WalkParts(fn func(int, types.Part, error) bool) { 65 e.source.Iter(func(i int, p types.Part) error { 66 var err error 67 if e.partErrors == nil { 68 err = e.err 69 } else { 70 err = e.partErrors[i] 71 } 72 if !fn(i, p, err) { 73 return errors.New("stop") 74 } 75 return nil 76 }) 77 } 78 79 // Error implements the common error interface. 80 func (e *Error) Error() string { 81 return e.err.Error() 82 } 83 84 // Unwrap returns the underlying common error. 85 func (e *Error) Unwrap() error { 86 return e.err 87 }