go-redis
go-redis copied to clipboard
XREADs with BLOCK 0 on multiple consecutive Redis restarts exceed retries
@lippserd just had the observation that blocking XREADs without timeouts (BLOCK 0) on multiple consecutive Redis restarts and I/O timeouts exceeds Go-Redis internal retries and eventually leads to errors. @julianbrost looked at this for clarification, here is his finding:
go-redis only considers a command successful when it returned something, so a successfully started blocking XREAD consumes a retry attempt each time the underlying Redis connection is terminated. If this happens often before any element appears in the stream, this error is propagated.
Expected Behavior
Successfully sent XREADs with BLOCK reset the internal retries.
Current Behavior
Successfully sent XREADs with BLOCK just failed while reading consume internal retries.
Possible Solution
Steps to Reproduce
Context (Environment)
refs Icinga/icingadb#504
Dear maintainers,
any objections against extending Cmder (or just XStreamSliceCmd) by a flag for whether successfully written and one for whether that's enough?
So baseClient#process could communicate with baseClient#_process and set attempt=-1 if needed.
And finally I could reproduce it as well:
- Run the below program
- Every time it prints success restart your Redis server
- It should not survive 4 restarts
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v9"
"net"
"time"
)
func main() {
var d net.Dialer
err := redis.NewClient(&redis.Options{
Addr: "127.0.0.1:6379",
Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) {
for {
conn, err := d.DialContext(ctx, network, addr)
if err != nil {
fmt.Println(err)
time.Sleep(time.Second)
continue
}
fmt.Println("success")
return conn, err
}
},
ReadTimeout: time.Hour,
PoolSize: 1,
}).XRead(context.Background(), &redis.XReadArgs{
Streams: []string{"block0", "$"},
Block: 0,
}).Err()
if err != nil {
panic(err)
}
}
This issue is marked stale. It will be closed in 30 days if it is not updated.