package main import ( "context" "fmt" "log" "os" "os/signal" "syscall" "time" valkey "github.com/redis/go-redis/v9" ) func main() { url := os.Args[1] ctx := context.Background() opt, err := valkey.ParseURL(url) if err != nil { panic(err) } client := valkey.NewClient(opt) if err != nil { panic(err) } defer client.Close() if err := client.Ping(ctx).Err(); err != nil { panic(err) } spans := poll(ctx, client) format := "15:04:05" for i, span := range spans.Spans { log.Printf("[%d] (%vs) %v .. %v", i, int(span[1].Sub(span[0]).Seconds()), span[0].Format(format), span[1].Format(format)) if i < len(spans.Spans)-1 { log.Printf("[%d] (%vs...)", i, int(spans.Spans[i+1][0].Sub(span[1]).Seconds())) } } misses := 0 for i, write := range spans.Writes { result := client.Get(ctx, write) if err := result.Err(); err != nil { misses += 1 log.Printf("[%d] expected %s but %v", i, write, err) } } log.Printf("cannot confirm %d/%d entries", misses, len(spans.Writes)) } type Poll struct { Spans [][2]time.Time Writes []string } func poll(ctx context.Context, client *valkey.Client) Poll { ctx, can := signal.NotifyContext(context.Background(), syscall.SIGINT) defer can() spans := [][2]time.Time{ {time.Now(), time.Now()}, } writes := []string{} for ctx.Err() == nil { waitFailure(ctx, client, func(s string) { writes = append(writes, s) }) spans[len(spans)-1][1] = time.Now() waitSuccess(ctx, client, func(s string) { writes = append(writes, s) }) now := time.Now() spans = append(spans, [2]time.Time{now, now}) } if last := spans[len(spans)-1]; last[1] == last[0] { spans = spans[:len(spans)-1] } return Poll{Spans: spans, Writes: writes} } func waitFailure(ctx context.Context, client *valkey.Client, cb func(string)) { waitResult(ctx, client, false, cb) } func waitSuccess(ctx context.Context, client *valkey.Client, cb func(string)) { waitResult(ctx, client, true, cb) } func waitResult(ctx context.Context, client *valkey.Client, wantOK bool, cb func(string)) { wait(ctx, func() bool { k := time.Now().String() result := client.Do(ctx, "SET", k, "ok") err := result.Err() got := err == nil if got { cb(k) } if got != wantOK { fmt.Fprintf(os.Stderr, ".") } else if wantOK { fmt.Fprintf(os.Stderr, "\n") log.Println("okay!") } else { fmt.Fprintf(os.Stderr, "\n") log.Println("failed!") } return got == wantOK }) } func wait(ctx context.Context, foo func() bool) { c := time.NewTicker(250 * time.Millisecond) defer c.Stop() for { select { case <-c.C: case <-ctx.Done(): fmt.Println() return } if foo() { return } } }