github.com/Jeffail/benthos/v3@v3.65.0/internal/batch/combined_ack_func.go (about) 1 package batch 2 3 import ( 4 "context" 5 "sync" 6 ) 7 8 // AckFunc is a common function signature for acknowledging receipt of messages. 9 type AckFunc func(context.Context, error) error 10 11 // CombinedAcker creates a single ack func closure that aggregates one or more 12 // derived closures such that only once each derived closure is called the 13 // singular ack func will trigger. If at least one derived closure receives an 14 // error the singular ack func will send the first non-nil error received. 15 type CombinedAcker struct { 16 mut sync.Mutex 17 remainingAcks int 18 err error 19 root AckFunc 20 } 21 22 // NewCombinedAcker creates an aggregated that derives one or more ack funcs 23 // that, once all of which have been called, the provided root ack func is 24 // called. 25 func NewCombinedAcker(aFn AckFunc) *CombinedAcker { 26 return &CombinedAcker{ 27 remainingAcks: 0, 28 root: aFn, 29 } 30 } 31 32 // Derive creates a new ack func that must be called before the origin ack func 33 // will be called. It is invalid to derive an ack func after any other 34 // previously derived funcs have been called. 35 func (c *CombinedAcker) Derive() AckFunc { 36 c.mut.Lock() 37 c.remainingAcks++ 38 c.mut.Unlock() 39 40 var decrementOnce sync.Once 41 return func(ctx context.Context, ackErr error) (err error) { 42 decrementOnce.Do(func() { 43 c.mut.Lock() 44 c.remainingAcks-- 45 remaining := c.remainingAcks 46 if ackErr != nil { 47 c.err = ackErr 48 } 49 ackErr = c.err 50 c.mut.Unlock() 51 if remaining == 0 { 52 err = c.root(ctx, ackErr) 53 } 54 }) 55 return 56 } 57 }