github.com/Jeffail/benthos/v3@v3.65.0/lib/output/writer/batched_send.go (about)

     1  package writer
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/Jeffail/benthos/v3/internal/batch"
     7  	"github.com/Jeffail/benthos/v3/lib/types"
     8  )
     9  
    10  // Returns true if the error should break a batch send loop.
    11  func sendErrIsFatal(err error) bool {
    12  	if errors.Is(err, types.ErrTypeClosed) {
    13  		return true
    14  	}
    15  	if errors.Is(err, types.ErrNotConnected) {
    16  		return true
    17  	}
    18  	if errors.Is(err, types.ErrTimeout) {
    19  		return true
    20  	}
    21  	return false
    22  }
    23  
    24  // IterateBatchedSend executes a closure fn on each message of a batch, where
    25  // the closure is expected to attempt a send and return an error. If an error is
    26  // returned then it is added to a batch error in order to support index specific
    27  // error handling.
    28  //
    29  // However, if a fatal error is returned such as a connection loss or shut down
    30  // then it is returned immediately.
    31  func IterateBatchedSend(msg types.Message, fn func(int, types.Part) error) error {
    32  	if msg.Len() == 1 {
    33  		return fn(0, msg.Get(0))
    34  	}
    35  	var batchErr *batch.Error
    36  	if err := msg.Iter(func(i int, p types.Part) error {
    37  		tmpErr := fn(i, p)
    38  		if tmpErr != nil {
    39  			if sendErrIsFatal(tmpErr) {
    40  				return tmpErr
    41  			}
    42  			if batchErr == nil {
    43  				batchErr = batch.NewError(msg, tmpErr)
    44  			}
    45  			batchErr.Failed(i, tmpErr)
    46  		}
    47  		return nil
    48  	}); err != nil {
    49  		return err
    50  	}
    51  	if batchErr != nil {
    52  		return batchErr
    53  	}
    54  	return nil
    55  }