1
0
mirror of https://github.com/redis/go-redis.git synced 2025-12-02 06:22:31 +03:00
Files
go-redis/autopipeline_sequential_test.go
2025-10-27 16:08:40 +02:00

152 lines
3.4 KiB
Go

package redis_test
import (
"context"
"fmt"
"testing"
"time"
"github.com/redis/go-redis/v9"
)
func TestAutoPipelineSequential(t *testing.T) {
ctx := context.Background()
client := redis.NewClient(&redis.Options{
Addr: ":6379",
AutoPipelineConfig: &redis.AutoPipelineConfig{
MaxBatchSize: 10,
FlushInterval: 50 * time.Millisecond,
MaxConcurrentBatches: 5,
},
})
defer client.Close()
if err := client.FlushDB(ctx).Err(); err != nil {
t.Fatal(err)
}
ap := client.AutoPipeline()
defer ap.Close()
// Sequential usage - no goroutines needed!
// Commands will be queued and batched automatically
cmds := make([]redis.Cmder, 20)
for i := 0; i < 20; i++ {
key := fmt.Sprintf("key%d", i)
cmds[i] = ap.Do(ctx, "SET", key, i)
}
// Now access results - this will block until commands execute
for i, cmd := range cmds {
if err := cmd.Err(); err != nil {
t.Fatalf("Command %d failed: %v", i, err)
}
}
// Verify all keys were set
for i := 0; i < 20; i++ {
key := fmt.Sprintf("key%d", i)
val, err := client.Get(ctx, key).Int()
if err != nil {
t.Fatalf("Failed to get %s: %v", key, err)
}
if val != i {
t.Fatalf("Expected %d, got %d", i, val)
}
}
}
func TestAutoPipelineSequentialSmallBatches(t *testing.T) {
ctx := context.Background()
client := redis.NewClient(&redis.Options{
Addr: ":6379",
AutoPipelineConfig: &redis.AutoPipelineConfig{
MaxBatchSize: 1000, // Large batch size
FlushInterval: 20 * time.Millisecond, // Rely on timer
MaxConcurrentBatches: 5,
},
})
defer client.Close()
if err := client.FlushDB(ctx).Err(); err != nil {
t.Fatal(err)
}
ap := client.AutoPipeline()
defer ap.Close()
// Queue commands sequentially with small delays
// They should be flushed by timer, not batch size
for i := 0; i < 5; i++ {
key := fmt.Sprintf("key%d", i)
cmd := ap.Do(ctx, "SET", key, i)
// Access result immediately - should block until flush
if err := cmd.Err(); err != nil {
t.Fatalf("Command %d failed: %v", i, err)
}
time.Sleep(5 * time.Millisecond)
}
// Verify all keys were set
for i := 0; i < 5; i++ {
key := fmt.Sprintf("key%d", i)
val, err := client.Get(ctx, key).Int()
if err != nil {
t.Fatalf("Failed to get %s: %v", key, err)
}
if val != i {
t.Fatalf("Expected %d, got %d", i, val)
}
}
}
func TestAutoPipelineSequentialMixed(t *testing.T) {
ctx := context.Background()
client := redis.NewClient(&redis.Options{
Addr: ":6379",
AutoPipelineConfig: &redis.AutoPipelineConfig{
MaxBatchSize: 5,
FlushInterval: 50 * time.Millisecond,
MaxConcurrentBatches: 5,
},
})
defer client.Close()
if err := client.FlushDB(ctx).Err(); err != nil {
t.Fatal(err)
}
ap := client.AutoPipeline()
defer ap.Close()
// Queue some commands
cmd1 := ap.Do(ctx, "SET", "key1", "value1")
cmd2 := ap.Do(ctx, "SET", "key2", "value2")
cmd3 := ap.Do(ctx, "SET", "key3", "value3")
// Access first result - should trigger batch flush
if err := cmd1.Err(); err != nil {
t.Fatalf("cmd1 failed: %v", err)
}
// Other commands in same batch should also be done
if err := cmd2.Err(); err != nil {
t.Fatalf("cmd2 failed: %v", err)
}
if err := cmd3.Err(); err != nil {
t.Fatalf("cmd3 failed: %v", err)
}
// Verify
val, err := client.Get(ctx, "key1").Result()
if err != nil || val != "value1" {
t.Fatalf("key1: expected value1, got %v, err %v", val, err)
}
}