package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/go-redis/redis/v8"
	"github.com/pborman/getopt/v2"
)

var ctx = context.Background()

func main() {

	helpFlag := getopt.BoolLong("help", 'h', "display help")
	redisHost := getopt.StringLong("host", 's', "", "name or IP of any cluster node")
	redisPort := getopt.IntLong("port", 'p', 6379, "port for the cluster node")
	redisPassword := getopt.StringLong("password", 'a', "", "cluster password")
	messageCount := getopt.IntLong("message-count", 'm', 10000, "Message count")
	minBackOff := getopt.IntLong("min-backoff", 'i', 500, "ms to start backoff")
	maxBackOff := getopt.IntLong("max-backoff", 'x', 1000, "ms to start backoff")

	getopt.Parse()

	if *helpFlag || *redisHost == "" {
		getopt.PrintUsage(os.Stderr)
		os.Exit(1)
	}

	client := redis.NewClusterClient(&redis.ClusterOptions{
		Addrs:           []string{fmt.Sprintf("%s:%d", *redisHost, *redisPort)},
		MaxRedirects:    3,
		Password:        *redisPassword,
		PoolSize:        8,
		MinRetryBackoff: time.Duration(*minBackOff) * time.Millisecond,
		MaxRetryBackoff: time.Duration(*maxBackOff) * time.Millisecond,
		MinIdleConns:    5,
		PoolTimeout:     0,
		ReadTimeout:     4 * time.Millisecond,
		WriteTimeout:    4 * time.Millisecond,
		IdleTimeout:     20 * time.Second,
		DialTimeout:     2 * time.Second,
	})
	client.Ping(ctx)
	for i := 0; i < *messageCount; i++ {
		start := time.Now()
		misses := client.PoolStats().Misses
		_, err := client.Set(ctx, "DTM", "DTM", 0).Result()
		elapsed := time.Since(start)
		if err != nil {
			fmt.Println(err)
		}
		if client.PoolStats().Misses > misses && elapsed.Milliseconds() > 1 {
			log.Printf("Failover: Client took %d ms to complete operation %+v\n", elapsed.Milliseconds(), client.PoolStats())
		}

	}

}
