package redis

import (
	
	
	
	
	
	
	
	
	
	

	
	
	
	
)
Limiter is the interface of a rate limiter or a circuit breaker.
Allow returns nil if operation is allowed or an error otherwise. If operation is allowed client must ReportResult of the operation whether it is a success or a failure.
ReportResult reports the result of the previously allowed operation. nil indicates a success, non-nil error usually indicates a failure.
	ReportResult(result error)
}

The network type, either tcp or unix. Default is tcp.
host:port address.
Dialer creates new network connection and has priority over Network and Addr options.
	Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
Hook that is called when new connection is established.
Use the specified Username to authenticate the current connection with one of the connections defined in the ACL list when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
Optional password. Must match the password specified in the requirepass server configuration option (if connecting to a Redis 5.0 instance, or lower), or the User Password when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
Database to be selected after connecting to the server.
Maximum number of retries before giving up. Default is 3 retries.
Minimum backoff between each retry. Default is 8 milliseconds; -1 disables backoff.
Maximum backoff between each retry. Default is 512 milliseconds; -1 disables backoff.
Dial timeout for establishing new connections. Default is 5 seconds.
Timeout for socket reads. If reached, commands will fail with a timeout instead of blocking. Use value -1 for no timeout and 0 for default. Default is 3 seconds.
Timeout for socket writes. If reached, commands will fail with a timeout instead of blocking. Default is ReadTimeout.
Maximum number of socket connections. Default is 10 connections per every CPU as reported by runtime.NumCPU.
Minimum number of idle connections which is useful when establishing new connection is slow.
Connection age at which client retires (closes) the connection. Default is to not close aged connections.
Amount of time client waits for connection if all connections are busy before returning an error. Default is ReadTimeout + 1 second.
Amount of time after which client closes idle connections. Should be less than server's timeout. Default is 5 minutes. -1 disables idle timeout check.
Frequency of idle checks made by idle connections reaper. Default is 1 minute. -1 disables idle connections reaper, but idle connections are still discarded by the client if IdleTimeout is set.
Enables read only queries on slave nodes.
TLS Config to use. When set TLS will be negotiated.
Limiter interface used to implemented circuit breaker or rate limiter.
	Limiter Limiter
}

func ( *Options) () {
	if .Addr == "" {
		.Addr = "localhost:6379"
	}
	if .Network == "" {
		if strings.HasPrefix(.Addr, "/") {
			.Network = "unix"
		} else {
			.Network = "tcp"
		}
	}
	if .DialTimeout == 0 {
		.DialTimeout = 5 * time.Second
	}
	if .Dialer == nil {
		.Dialer = func( context.Context, ,  string) (net.Conn, error) {
			 := &net.Dialer{
				Timeout:   .DialTimeout,
				KeepAlive: 5 * time.Minute,
			}
			if .TLSConfig == nil {
				return .DialContext(, , )
			}
			return tls.DialWithDialer(, , , .TLSConfig)
		}
	}
	if .PoolSize == 0 {
		.PoolSize = 10 * runtime.NumCPU()
	}
	switch .ReadTimeout {
	case -1:
		.ReadTimeout = 0
	case 0:
		.ReadTimeout = 3 * time.Second
	}
	switch .WriteTimeout {
	case -1:
		.WriteTimeout = 0
	case 0:
		.WriteTimeout = .ReadTimeout
	}
	if .PoolTimeout == 0 {
		.PoolTimeout = .ReadTimeout + time.Second
	}
	if .IdleTimeout == 0 {
		.IdleTimeout = 5 * time.Minute
	}
	if .IdleCheckFrequency == 0 {
		.IdleCheckFrequency = time.Minute
	}

	if .MaxRetries == -1 {
		.MaxRetries = 0
	} else if .MaxRetries == 0 {
		.MaxRetries = 3
	}
	switch .MinRetryBackoff {
	case -1:
		.MinRetryBackoff = 0
	case 0:
		.MinRetryBackoff = 8 * time.Millisecond
	}
	switch .MaxRetryBackoff {
	case -1:
		.MaxRetryBackoff = 0
	case 0:
		.MaxRetryBackoff = 512 * time.Millisecond
	}
}

func ( *Options) () *Options {
	 := *
	return &
}
ParseURL parses an URL into Options that can be used to connect to Redis.
func ( string) (*Options, error) {
	 := &Options{Network: "tcp"}
	,  := url.Parse()
	if  != nil {
		return nil, 
	}

	if .Scheme != "redis" && .Scheme != "rediss" {
		return nil, errors.New("invalid redis URL scheme: " + .Scheme)
	}

	if .User != nil {
		.Username = .User.Username()
		if ,  := .User.Password();  {
			.Password = 
		}
	}

	if len(.Query()) > 0 {
		return nil, errors.New("no options supported")
	}

	, ,  := net.SplitHostPort(.Host)
	if  != nil {
		 = .Host
	}
	if  == "" {
		 = "localhost"
	}
	if  == "" {
		 = "6379"
	}
	.Addr = net.JoinHostPort(, )

	 := strings.FieldsFunc(.Path, func( rune) bool {
		return  == '/'
	})
	switch len() {
	case 0:
		.DB = 0
	case 1:
		if .DB,  = strconv.Atoi([0]);  != nil {
			return nil, fmt.Errorf("invalid redis database number: %q", [0])
		}
	default:
		return nil, errors.New("invalid redis URL path: " + .Path)
	}

	if .Scheme == "rediss" {
		.TLSConfig = &tls.Config{ServerName: }
	}
	return , nil
}

func ( *Options) *pool.ConnPool {
	return pool.NewConnPool(&pool.Options{
		Dialer: func( context.Context) (net.Conn, error) {
			var  net.Conn
			 := internal.WithSpan(, "dialer", func( context.Context) error {
				var  error
				trace.SpanFromContext().SetAttributes(
					label.String("redis.network", .Network),
					label.String("redis.addr", .Addr),
				)
				,  = .Dialer(, .Network, .Addr)
				if  != nil {
					_ = internal.RecordError(, )
				}
				return 
			})
			return , 
		},
		PoolSize:           .PoolSize,
		MinIdleConns:       .MinIdleConns,
		MaxConnAge:         .MaxConnAge,
		PoolTimeout:        .PoolTimeout,
		IdleTimeout:        .IdleTimeout,
		IdleCheckFrequency: .IdleCheckFrequency,
	})