mirror of
https://github.com/redis/go-redis.git
synced 2025-11-05 14:10:37 +03:00
Add support for XReadGroup CLAIM argument (#3578)
* Add support for XReadGroup CLAIM argument * modify tutorial tests --------- Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com>
This commit is contained in:
236
commands_test.go
236
commands_test.go
@@ -6749,6 +6749,242 @@ var _ = Describe("Commands", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(n).To(Equal(int64(2)))
|
||||
})
|
||||
|
||||
It("should XReadGroup with CLAIM argument", func() {
|
||||
SkipBeforeRedisVersion(8.3, "XREADGROUP CLAIM requires Redis 8.3+")
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
res, err := client.XReadGroup(ctx, &redis.XReadGroupArgs{
|
||||
Group: "group",
|
||||
Consumer: "consumer2",
|
||||
Streams: []string{"stream", ">"},
|
||||
Claim: 50 * time.Millisecond,
|
||||
}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res).To(HaveLen(1))
|
||||
Expect(res[0].Stream).To(Equal("stream"))
|
||||
|
||||
messages := res[0].Messages
|
||||
Expect(len(messages)).To(BeNumerically(">=", 1))
|
||||
|
||||
for _, msg := range messages {
|
||||
if msg.MillisElapsedFromDelivery > 0 {
|
||||
Expect(msg.MillisElapsedFromDelivery).To(BeNumerically(">=", 50))
|
||||
Expect(msg.DeliveredCount).To(BeNumerically(">=", 1))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
It("should XReadGroup with CLAIM and COUNT", func() {
|
||||
SkipBeforeRedisVersion(8.3, "XREADGROUP CLAIM requires Redis 8.3+")
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
res, err := client.XReadGroup(ctx, &redis.XReadGroupArgs{
|
||||
Group: "group",
|
||||
Consumer: "consumer3",
|
||||
Streams: []string{"stream", ">"},
|
||||
Claim: 50 * time.Millisecond,
|
||||
Count: 2,
|
||||
}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
if len(res) > 0 && len(res[0].Messages) > 0 {
|
||||
Expect(len(res[0].Messages)).To(BeNumerically("<=", 2))
|
||||
}
|
||||
})
|
||||
|
||||
It("should XReadGroup with CLAIM and NOACK", func() {
|
||||
SkipBeforeRedisVersion(8.3, "XREADGROUP CLAIM requires Redis 8.3+")
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
res, err := client.XReadGroup(ctx, &redis.XReadGroupArgs{
|
||||
Group: "group",
|
||||
Consumer: "consumer4",
|
||||
Streams: []string{"stream", ">"},
|
||||
Claim: 50 * time.Millisecond,
|
||||
NoAck: true,
|
||||
}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
if len(res) > 0 {
|
||||
Expect(res[0].Stream).To(Equal("stream"))
|
||||
}
|
||||
})
|
||||
|
||||
It("should XReadGroup CLAIM empties PEL after acknowledgment", func() {
|
||||
SkipBeforeRedisVersion(8.3, "XREADGROUP CLAIM requires Redis 8.3+")
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
res, err := client.XReadGroup(ctx, &redis.XReadGroupArgs{
|
||||
Group: "group",
|
||||
Consumer: "consumer5",
|
||||
Streams: []string{"stream", ">"},
|
||||
Claim: 50 * time.Millisecond,
|
||||
}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
if len(res) > 0 && len(res[0].Messages) > 0 {
|
||||
ids := make([]string, len(res[0].Messages))
|
||||
for i, msg := range res[0].Messages {
|
||||
ids[i] = msg.ID
|
||||
}
|
||||
|
||||
n, err := client.XAck(ctx, "stream", "group", ids...).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(n).To(BeNumerically(">=", 1))
|
||||
|
||||
pending, err := client.XPending(ctx, "stream", "group").Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(pending.Count).To(BeNumerically("<", 3))
|
||||
}
|
||||
})
|
||||
|
||||
It("should XReadGroup backward compatibility without CLAIM", func() {
|
||||
res, err := client.XReadGroup(ctx, &redis.XReadGroupArgs{
|
||||
Group: "group",
|
||||
Consumer: "consumer_compat",
|
||||
Streams: []string{"stream", "0"},
|
||||
}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res).To(HaveLen(1))
|
||||
Expect(res[0].Stream).To(Equal("stream"))
|
||||
|
||||
for _, msg := range res[0].Messages {
|
||||
Expect(msg.MillisElapsedFromDelivery).To(Equal(int64(0)))
|
||||
Expect(msg.DeliveredCount).To(Equal(int64(0)))
|
||||
}
|
||||
})
|
||||
|
||||
It("should XReadGroup CLAIM with multiple streams", func() {
|
||||
SkipBeforeRedisVersion(8.3, "XREADGROUP CLAIM requires Redis 8.3+")
|
||||
|
||||
id, err := client.XAdd(ctx, &redis.XAddArgs{
|
||||
Stream: "stream2",
|
||||
ID: "1-0",
|
||||
Values: map[string]interface{}{"field1": "value1"},
|
||||
}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(id).To(Equal("1-0"))
|
||||
|
||||
id, err = client.XAdd(ctx, &redis.XAddArgs{
|
||||
Stream: "stream2",
|
||||
ID: "2-0",
|
||||
Values: map[string]interface{}{"field2": "value2"},
|
||||
}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(id).To(Equal("2-0"))
|
||||
|
||||
err = client.XGroupCreate(ctx, "stream2", "group2", "0").Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err = client.XReadGroup(ctx, &redis.XReadGroupArgs{
|
||||
Group: "group2",
|
||||
Consumer: "consumer1",
|
||||
Streams: []string{"stream2", ">"},
|
||||
}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
res, err := client.XReadGroup(ctx, &redis.XReadGroupArgs{
|
||||
Group: "group2",
|
||||
Consumer: "consumer2",
|
||||
Streams: []string{"stream2", ">"},
|
||||
Claim: 50 * time.Millisecond,
|
||||
}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
if len(res) > 0 {
|
||||
Expect(res[0].Stream).To(Equal("stream2"))
|
||||
if len(res[0].Messages) > 0 {
|
||||
for _, msg := range res[0].Messages {
|
||||
if msg.MillisElapsedFromDelivery > 0 {
|
||||
Expect(msg.DeliveredCount).To(BeNumerically(">=", 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
It("should XReadGroup CLAIM work consistently on RESP2 and RESP3", func() {
|
||||
SkipBeforeRedisVersion(8.3, "XREADGROUP CLAIM requires Redis 8.3+")
|
||||
|
||||
streamName := "stream-resp-test"
|
||||
err := client.XAdd(ctx, &redis.XAddArgs{
|
||||
Stream: streamName,
|
||||
Values: map[string]interface{}{"field1": "value1"},
|
||||
}).Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = client.XAdd(ctx, &redis.XAddArgs{
|
||||
Stream: streamName,
|
||||
Values: map[string]interface{}{"field2": "value2"},
|
||||
}).Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
groupName := "resp-test-group"
|
||||
err = client.XGroupCreate(ctx, streamName, groupName, "0").Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err = client.XReadGroup(ctx, &redis.XReadGroupArgs{
|
||||
Group: groupName,
|
||||
Consumer: "consumer1",
|
||||
Streams: []string{streamName, ">"},
|
||||
}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
// Test with RESP2 (protocol 2)
|
||||
resp2Client := redis.NewClient(&redis.Options{
|
||||
Addr: redisAddr,
|
||||
Protocol: 2,
|
||||
})
|
||||
defer resp2Client.Close()
|
||||
|
||||
resp2Result, err := resp2Client.XReadGroup(ctx, &redis.XReadGroupArgs{
|
||||
Group: groupName,
|
||||
Consumer: "consumer2",
|
||||
Streams: []string{streamName, "0"},
|
||||
Claim: 50 * time.Millisecond,
|
||||
}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(resp2Result).To(HaveLen(1))
|
||||
|
||||
// Test with RESP3 (protocol 3)
|
||||
resp3Client := redis.NewClient(&redis.Options{
|
||||
Addr: redisAddr,
|
||||
Protocol: 3,
|
||||
})
|
||||
defer resp3Client.Close()
|
||||
|
||||
resp3Result, err := resp3Client.XReadGroup(ctx, &redis.XReadGroupArgs{
|
||||
Group: groupName,
|
||||
Consumer: "consumer3",
|
||||
Streams: []string{streamName, "0"},
|
||||
Claim: 50 * time.Millisecond,
|
||||
}).Result()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(resp3Result).To(HaveLen(1))
|
||||
|
||||
Expect(len(resp2Result[0].Messages)).To(Equal(len(resp3Result[0].Messages)))
|
||||
|
||||
for i := range resp2Result[0].Messages {
|
||||
msg2 := resp2Result[0].Messages[i]
|
||||
msg3 := resp3Result[0].Messages[i]
|
||||
|
||||
Expect(msg2.ID).To(Equal(msg3.ID))
|
||||
|
||||
if msg2.MillisElapsedFromDelivery > 0 {
|
||||
Expect(msg3.MillisElapsedFromDelivery).To(BeNumerically(">", 0))
|
||||
Expect(msg2.DeliveredCount).To(Equal(msg3.DeliveredCount))
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Describe("xinfo", func() {
|
||||
|
||||
Reference in New Issue
Block a user