go-redis icon indicating copy to clipboard operation
go-redis copied to clipboard

client hangs when non-blocking XREAD on empty streams

Open fizx opened this issue 2 years ago • 7 comments

Expected Behavior

Client should return an empty response.

Current Behavior

Client blocks forever, even with timeouts set..

Possible Solution

Will investigate.

Steps to Reproduce

package main

import (
	"context"
	"time"

	"github.com/go-redis/redis/v8"
)

func main() {
	re := redis.NewClient(&redis.Options{
		Addr:         "localhost:6379",
		ReadTimeout:  1 * time.Second,
		WriteTimeout: 1 * time.Second,
		MaxRetries:   0,
		PoolSize:     10,
		PoolTimeout:  1 * time.Second,
		DialTimeout:  1 * time.Second,
	})
	println("connected")
	read := re.XRead(context.Background(), &redis.XReadArgs{
		Streams: []string{"hi", "0"},
	})
	println("unreachable")
	println(read.Val())
}

fizx avatar Nov 05 '21 22:11 fizx

Same here with XReadGroup: It does not matter if block parameter is 0 or 1. It always blocks

Lobosque avatar Apr 24 '22 17:04 Lobosque

set block argument

	println("connected")
	read := re.XRead(context.Background(), &redis.XReadArgs{
		Streams: []string{"hi", "0"},
		Block:   time.Millisecond * 10, // set block arg
	})
	println("unreachable")
	println(read.Val())

capric8416 avatar May 05 '22 12:05 capric8416

why i not set block arg or set it to 0 or 1 do not work? if i not set block it should return immediately!

moyuduo avatar Jul 24 '22 04:07 moyuduo

I have found the same problem problem with XReadGroup, the solution for me was to set a small timeout and catch the timeout errors apart.

    readMessages, err := client.XReadGroup(ctx, &redis.XReadGroupArgs{
	Group:    groupName,
	Consumer: consumerName,
	Streams:  []string{streamName, ">"},
	Count:    0,
	Block:    1,
	NoAck:    false,
}).Result()

if err != nil && !os.IsTimeout(err) {
	return []redis.XMessage{}, err
}

Never the less the expected behavior should be that without specifying a Block value, it should not block the stream

gm9510 avatar Feb 15 '23 15:02 gm9510

I think I have the same problem z with pub/sub mechanism

janekolszak avatar Jul 03 '23 14:07 janekolszak

I also face the same problem, why use xread and xreadgroup will stuck, and i cant read any message. that's so shocking me.

fireinrain avatar Sep 06 '23 10:09 fireinrain

The API design of Redis Stream is damn... The default behavior of XREADGROUP of Redis is non-blocking, unless we set [BLOCK milliseconds]. Therefore, it is natural to think of using zero value in Go as the default value (default behavior). However, we take it for granted that this is right to 'just ignore setting the value of Block in XReadGroupArgs'.

The lib do this (as below) in XReadGroup, which means no value <=> set [BLOCK 0]:

if a.Block >= 0 {
  args = append(args, "block", int64(a.Block/time.Millisecond))
  keyPos += 2
}

The correct solution maybe assigns a negative value to Block like -time.Millisecond (but I would say it again that the API is damn...)

tzq0301 avatar Dec 27 '23 04:12 tzq0301