Exponential Backoff for ByteFIFO (#15724) (#15793)

This PR is another in the vein of queue improvements. It suggests an
exponential backoff for bytefifo queues to reduce the load from queue
polling. This will mostly be useful for redis queues.

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: Lauris BH <lauris@nix.lv>

Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: Lauris BH <lauris@nix.lv>
mj-v1.14.3
6543 3 years ago committed by GitHub
parent 30584a6df8
commit d644709b22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -114,41 +114,71 @@ func (q *ByteFIFOQueue) Run(atShutdown, atTerminate func(context.Context, func()
} }
func (q *ByteFIFOQueue) readToChan() { func (q *ByteFIFOQueue) readToChan() {
// handle quick cancels
select {
case <-q.closed:
// tell the pool to shutdown.
q.cancel()
return
default:
}
backOffTime := time.Millisecond * 100
maxBackOffTime := time.Second * 3
for { for {
success, resetBackoff := q.doPop()
if resetBackoff {
backOffTime = 100 * time.Millisecond
}
if success {
select { select {
case <-q.closed: case <-q.closed:
// tell the pool to shutdown. // tell the pool to shutdown.
q.cancel() q.cancel()
return return
default: default:
}
} else {
select {
case <-q.closed:
// tell the pool to shutdown.
q.cancel()
return
case <-time.After(backOffTime):
}
backOffTime += backOffTime / 2
if backOffTime > maxBackOffTime {
backOffTime = maxBackOffTime
}
}
}
}
func (q *ByteFIFOQueue) doPop() (success, resetBackoff bool) {
q.lock.Lock() q.lock.Lock()
defer q.lock.Unlock()
bs, err := q.byteFIFO.Pop() bs, err := q.byteFIFO.Pop()
if err != nil { if err != nil {
q.lock.Unlock()
log.Error("%s: %s Error on Pop: %v", q.typ, q.name, err) log.Error("%s: %s Error on Pop: %v", q.typ, q.name, err)
time.Sleep(time.Millisecond * 100) return
continue
} }
if len(bs) == 0 { if len(bs) == 0 {
q.lock.Unlock() return
time.Sleep(time.Millisecond * 100)
continue
} }
resetBackoff = true
data, err := unmarshalAs(bs, q.exemplar) data, err := unmarshalAs(bs, q.exemplar)
if err != nil { if err != nil {
log.Error("%s: %s Failed to unmarshal with error: %v", q.typ, q.name, err) log.Error("%s: %s Failed to unmarshal with error: %v", q.typ, q.name, err)
q.lock.Unlock() return
time.Sleep(time.Millisecond * 100)
continue
} }
log.Trace("%s %s: Task found: %#v", q.typ, q.name, data) log.Trace("%s %s: Task found: %#v", q.typ, q.name, data)
q.WorkerPool.Push(data) q.WorkerPool.Push(data)
q.lock.Unlock() success = true
} return
}
} }
// Shutdown processing from this queue // Shutdown processing from this queue

Loading…
Cancel
Save