bugfix: NackRedeliveryDelay may cause unexpected retry

This commit is contained in:
finley
2025-01-28 19:34:54 +08:00
parent 8dd18cdb15
commit a3020e2dd2

View File

@@ -512,11 +512,29 @@ func (q *DelayQueue) ack(idStr string) error {
return nil return nil
} }
// updateZSetScoreScript update score of a zset member if it exists
// KEYS[1]: zset
// ARGV[1]: score
// ARGV[2]: member
const updateZSetScoreScript = `
if redis.call('zrank', KEYS[1], ARGV[2]) ~= nil then
return redis.call('zadd', KEYS[1], ARGV[1], ARGV[2])
else
return 0
end
`
func (q *DelayQueue) updateZSetScore(key string, score float64, member string) error {
scoreStr := strconv.FormatFloat(score, 'f', -1, 64)
_, err := q.eval(updateZSetScoreScript, []string{key}, []interface{}{scoreStr, member})
return err
}
func (q *DelayQueue) nack(idStr string) error { func (q *DelayQueue) nack(idStr string) error {
atomic.AddInt32(&q.fetchCount, -1) atomic.AddInt32(&q.fetchCount, -1)
err := q.redisCli.ZAdd(q.unAckKey, map[string]float64{ retryTime := float64(time.Now().Add(q.nackRedeliveryDelay).Unix())
idStr: float64(time.Now().Add(q.nackRedeliveryDelay).Unix()), // if message consumption has not reach deadlin (still in unAckKey), then update its retry time
}) err := q.updateZSetScore(q.unAckKey, retryTime, idStr)
if err != nil { if err != nil {
return fmt.Errorf("negative ack failed: %v", err) return fmt.Errorf("negative ack failed: %v", err)
} }