sewenew / redis-plus-plus

Redis client written in C++
Apache License 2.0
1.64k stars 351 forks source link

[BUG] XREAD does not give an item with a greater ID #319

Closed RobinLanglois closed 2 years ago

RobinLanglois commented 2 years ago

Hello,

Describe the bug I'm looping over a stream with XREAD to read it entirely. At each iteration, I retrieve the ID given by the previous XREAD, and I'm giving this ID back to the next call of XREAD to have an item with a greater ID than this. But I'm getting the same item as before (so I'm not reading the stream but only the first one indefinitely).

To Reproduce My code looks like this :

// result as defined in documentation
string id = "0";
for (int i = 0; i < 50; i++) {
            redisServer.xread("stream-key", id, 1, std::inserter(result, result.end()));
            id = result["stream-key"][0].first;
}

And I'm still getting the same result item.

Expected behavior When I'm giving an ID, I'm expecting an item with a greater ID, as specified in Redis documentation : https://redis.io/commands/xread

Environment:

Thank you in advance.

wingunder commented 2 years ago

Hi @RobinLanglois,

The behavior that you explained is completely correct. You either need to XDEL the items that you would not like to read again, like in the example below, or you should use Consumer Groups, as explained in https://redis.io/topics/streams-intro.

$ redis-cli -h 10.10.10.1 -p 7001 -c
10.10.10.1:7001> XADD test.stream * a 1
"1643698909655-0"
10.10.10.1:7001> XADD test.stream * a 2
"1643698917944-0"
10.10.10.1:7001> XADD test.stream * a 3
"1643698920272-0"
10.10.10.1:7001> XREAD STREAMS test.stream 1643698909655-0
1) 1) "test.stream"
   2) 1) 1) "1643698917944-0"
         2) 1) "a"
            2) "2"
      2) 1) "1643698920272-0"
         2) 1) "a"
            2) "3"
10.10.10.1:7001> XREAD STREAMS test.stream 0
1) 1) "test.stream"
   2) 1) 1) "1643698909655-0"
         2) 1) "a"
            2) "1"
      2) 1) "1643698917944-0"
         2) 1) "a"
            2) "2"
      3) 1) "1643698920272-0"
         2) 1) "a"
            2) "3"
10.10.10.1:7001> XDEL test.stream 1643698909655-0
(integer) 1
10.10.10.1:7001> XREAD STREAMS test.stream 0
1) 1) "test.stream"
   2) 1) 1) "1643698917944-0"
         2) 1) "a"
            2) "2"
      2) 1) "1643698920272-0"
         2) 1) "a"
            2) "3"
10.10.10.1:7001>

I hope this helped you. Regards

sewenew commented 2 years ago

@RobinLanglois

You need to clear result before add new entries into it. Also you need to check if result is empty before accessing it:

for (int i = 0; i < 50; i++) {
            redisServer.xread("stream-key", id, 1, std::inserter(result, result.end()));
            if (result.empty()) break;
            id = result["stream-key"][0].first;
            // code processing result
            result.clear();
}

Regards

RobinLanglois commented 2 years ago

@sewenew Well that's a dumb error of mine :smile: Thanks to both of you. @wingunder maybe you misunderstood my problem, but as you showed here :

XREAD STREAMS test.stream 1643698909655-0
1) 1) "test.stream"
   2) 1) 1) "1643698917944-0"

XREAD always gives you an item with a greater ID than the one you gives. That was not my case because I appended all results in one variable, and was always looking for the first entry of my variable, thus always the same. Thank you anyway for trying to solve my problem :smile: Regards