mirror of
https://github.com/redis/go-redis.git
synced 2025-12-02 06:22:31 +03:00
152 lines
3.4 KiB
Go
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,
|
|
MaxFlushDelay: 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
|
|
MaxFlushDelay: 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,
|
|
MaxFlushDelay: 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)
|
|
}
|
|
}
|
|
|