Fix XREADGROUP CLAIM to return delivery metadata as integers (#14524)

### Problem
The XREADGROUP command with CLAIM parameter incorrectly returns delivery
metadata (idle time and delivery count) as strings instead of integers,
contradicting the Redis specification.

### Solution
Updated the XREADGROUP CLAIM implementation to return delivery metadata
fields as integers, aligning with the documented specification and
maintaining consistency with Redis response conventions.

---------

Co-authored-by: debing.sun <debing.sun@redis.com>
This commit is contained in:
Sergei Georgiev 2025-11-11 13:05:22 +02:00 committed by GitHub
parent d25e582a17
commit 90ba7ba4dc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 55 additions and 7 deletions

View file

@ -162,11 +162,11 @@
},
{
"description": "Milliseconds elapsed since last delivery",
"type": "string"
"type": "integer"
},
{
"description": "Delivery count (0 for new messages, 1+ for claimed messages)",
"type": "string"
"type": "integer"
}
]
}

View file

@ -1969,8 +1969,8 @@ size_t streamReplyWithRange(client *c, stream *s, streamID *start, streamID *end
}
uint64_t idle = cmd_time_snapshot - pelKey->delivery_time;
addReplyBulkLongLong(c, idle);
addReplyBulkLongLong(c, delivery_count);
addReplyLongLong(c, idle);
addReplyLongLong(c, delivery_count);
/* Remove the NACK from old consumer and time-based PEL. */
raxRemove(nack->consumer->pel,buf,sizeof(buf),NULL);
@ -2075,8 +2075,8 @@ size_t streamReplyWithRange(client *c, stream *s, streamID *start, streamID *end
if (min_idle_time != -1) {
/* For new entries idle time and delivery count is 0. */
addReplyBulkLongLong(c, 0);
addReplyBulkLongLong(c, 0);
addReplyLongLong(c, 0);
addReplyLongLong(c, 0);
}
/* If a group is passed, we need to create an entry in the

View file

@ -1879,6 +1879,54 @@ start_server {
}
start_server {} {
if {!$::force_resp3} {
test "XREADGROUP CLAIM field types are correct" {
r DEL mystream
r XADD mystream 1-0 f v1
r XGROUP CREATE mystream group1 0
# Read the message with XREADGROUP
r XREADGROUP GROUP group1 consumer1 STREAMS mystream >
# Wait to allow claiming
after 100
# Read again with CLAIM using readraw to check field types
r readraw 1
r deferred 1
r XREADGROUP GROUP group1 consumer2 CLAIM 50 STREAMS mystream >
# Check the response format line by line
# Response structure: *1 (outer array) -> *2 (stream name + messages array)
assert_equal [r read] {*1} ;# Outer array (1 stream)
assert_equal [r read] {*2} ;# Stream data (2 elements: stream name + messages)
assert_equal [r read] {$8} ;# Stream name length
assert_equal [r read] {mystream} ;# Stream name
assert_equal [r read] {*1} ;# Messages array (1 message)
assert_equal [r read] {*4} ;# Message with 4 fields
assert_equal [r read] {$3} ;# Field 1: Message ID length
assert_equal [r read] {1-0} ;# Field 1: Message ID value
assert_equal [r read] {*2} ;# Field 2: Field-value pairs array
assert_equal [r read] {$1} ;# Field-value pair: key length
assert_equal [r read] {f} ;# Field-value pair: key
assert_equal [r read] {$2} ;# Field-value pair: value length
assert_equal [r read] {v1} ;# Field-value pair: value
# Field 3: Delivery count - should be integer type (:)
set delivery_count_type [r read]
assert_match {:*} $delivery_count_type "Expected delivery count to be integer type (:), got: $delivery_count_type"
# Field 4: Idle time - should be integer type (:)
set idle_time_type [r read]
assert_match {:*} $idle_time_type "Expected idle time to be integer type (:), got: $idle_time_type"
}
}
# Restore connection state
r readraw 0
r deferred 0
test "XREADGROUP CLAIM returns unacknowledged messages" {
r DEL mystream
r XADD mystream 1-0 f v1
@ -2832,7 +2880,7 @@ start_server {
$rd close
}
test "READGROUP CLAIM verify claiming order" {
test "XREADGROUP CLAIM verify claiming order" {
r DEL mystream
r XADD mystream 1-0 f v1
r XADD mystream 2-0 f v2