...

Source file src/github.com/go-redis/redis/options.go

Documentation: github.com/go-redis/redis

     1  package redis
     2  
     3  import (
     4  	"crypto/tls"
     5  	"errors"
     6  	"fmt"
     7  	"net"
     8  	"net/url"
     9  	"runtime"
    10  	"strconv"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/go-redis/redis/internal/pool"
    15  )
    16  
    17  // Limiter is the interface of a rate limiter or a circuit breaker.
    18  type Limiter interface {
    19  	// Allow returns a nil if operation is allowed or an error otherwise.
    20  	// If operation is allowed client must report the result of operation
    21  	// whether is a success or a failure.
    22  	Allow() error
    23  	// ReportResult reports the result of previously allowed operation.
    24  	// nil indicates a success, non-nil error indicates a failure.
    25  	ReportResult(result error)
    26  }
    27  
    28  type Options struct {
    29  	// The network type, either tcp or unix.
    30  	// Default is tcp.
    31  	Network string
    32  	// host:port address.
    33  	Addr string
    34  
    35  	// Dialer creates new network connection and has priority over
    36  	// Network and Addr options.
    37  	Dialer func() (net.Conn, error)
    38  
    39  	// Hook that is called when new connection is established.
    40  	OnConnect func(*Conn) error
    41  
    42  	// Optional password. Must match the password specified in the
    43  	// requirepass server configuration option.
    44  	Password string
    45  	// Database to be selected after connecting to the server.
    46  	DB int
    47  
    48  	// Maximum number of retries before giving up.
    49  	// Default is to not retry failed commands.
    50  	MaxRetries int
    51  	// Minimum backoff between each retry.
    52  	// Default is 8 milliseconds; -1 disables backoff.
    53  	MinRetryBackoff time.Duration
    54  	// Maximum backoff between each retry.
    55  	// Default is 512 milliseconds; -1 disables backoff.
    56  	MaxRetryBackoff time.Duration
    57  
    58  	// Dial timeout for establishing new connections.
    59  	// Default is 5 seconds.
    60  	DialTimeout time.Duration
    61  	// Timeout for socket reads. If reached, commands will fail
    62  	// with a timeout instead of blocking. Use value -1 for no timeout and 0 for default.
    63  	// Default is 3 seconds.
    64  	ReadTimeout time.Duration
    65  	// Timeout for socket writes. If reached, commands will fail
    66  	// with a timeout instead of blocking.
    67  	// Default is ReadTimeout.
    68  	WriteTimeout time.Duration
    69  
    70  	// Maximum number of socket connections.
    71  	// Default is 10 connections per every CPU as reported by runtime.NumCPU.
    72  	PoolSize int
    73  	// Minimum number of idle connections which is useful when establishing
    74  	// new connection is slow.
    75  	MinIdleConns int
    76  	// Connection age at which client retires (closes) the connection.
    77  	// Default is to not close aged connections.
    78  	MaxConnAge time.Duration
    79  	// Amount of time client waits for connection if all connections
    80  	// are busy before returning an error.
    81  	// Default is ReadTimeout + 1 second.
    82  	PoolTimeout time.Duration
    83  	// Amount of time after which client closes idle connections.
    84  	// Should be less than server's timeout.
    85  	// Default is 5 minutes. -1 disables idle timeout check.
    86  	IdleTimeout time.Duration
    87  	// Frequency of idle checks made by idle connections reaper.
    88  	// Default is 1 minute. -1 disables idle connections reaper,
    89  	// but idle connections are still discarded by the client
    90  	// if IdleTimeout is set.
    91  	IdleCheckFrequency time.Duration
    92  
    93  	// Enables read only queries on slave nodes.
    94  	readOnly bool
    95  
    96  	// TLS Config to use. When set TLS will be negotiated.
    97  	TLSConfig *tls.Config
    98  }
    99  
   100  func (opt *Options) init() {
   101  	if opt.Network == "" {
   102  		opt.Network = "tcp"
   103  	}
   104  	if opt.Addr == "" {
   105  		opt.Addr = "localhost:6379"
   106  	}
   107  	if opt.Dialer == nil {
   108  		opt.Dialer = func() (net.Conn, error) {
   109  			netDialer := &net.Dialer{
   110  				Timeout:   opt.DialTimeout,
   111  				KeepAlive: 5 * time.Minute,
   112  			}
   113  			if opt.TLSConfig == nil {
   114  				return netDialer.Dial(opt.Network, opt.Addr)
   115  			} else {
   116  				return tls.DialWithDialer(netDialer, opt.Network, opt.Addr, opt.TLSConfig)
   117  			}
   118  		}
   119  	}
   120  	if opt.PoolSize == 0 {
   121  		opt.PoolSize = 10 * runtime.NumCPU()
   122  	}
   123  	if opt.DialTimeout == 0 {
   124  		opt.DialTimeout = 5 * time.Second
   125  	}
   126  	switch opt.ReadTimeout {
   127  	case -1:
   128  		opt.ReadTimeout = 0
   129  	case 0:
   130  		opt.ReadTimeout = 3 * time.Second
   131  	}
   132  	switch opt.WriteTimeout {
   133  	case -1:
   134  		opt.WriteTimeout = 0
   135  	case 0:
   136  		opt.WriteTimeout = opt.ReadTimeout
   137  	}
   138  	if opt.PoolTimeout == 0 {
   139  		opt.PoolTimeout = opt.ReadTimeout + time.Second
   140  	}
   141  	if opt.IdleTimeout == 0 {
   142  		opt.IdleTimeout = 5 * time.Minute
   143  	}
   144  	if opt.IdleCheckFrequency == 0 {
   145  		opt.IdleCheckFrequency = time.Minute
   146  	}
   147  
   148  	switch opt.MinRetryBackoff {
   149  	case -1:
   150  		opt.MinRetryBackoff = 0
   151  	case 0:
   152  		opt.MinRetryBackoff = 8 * time.Millisecond
   153  	}
   154  	switch opt.MaxRetryBackoff {
   155  	case -1:
   156  		opt.MaxRetryBackoff = 0
   157  	case 0:
   158  		opt.MaxRetryBackoff = 512 * time.Millisecond
   159  	}
   160  }
   161  
   162  // ParseURL parses an URL into Options that can be used to connect to Redis.
   163  func ParseURL(redisURL string) (*Options, error) {
   164  	o := &Options{Network: "tcp"}
   165  	u, err := url.Parse(redisURL)
   166  	if err != nil {
   167  		return nil, err
   168  	}
   169  
   170  	if u.Scheme != "redis" && u.Scheme != "rediss" {
   171  		return nil, errors.New("invalid redis URL scheme: " + u.Scheme)
   172  	}
   173  
   174  	if u.User != nil {
   175  		if p, ok := u.User.Password(); ok {
   176  			o.Password = p
   177  		}
   178  	}
   179  
   180  	if len(u.Query()) > 0 {
   181  		return nil, errors.New("no options supported")
   182  	}
   183  
   184  	h, p, err := net.SplitHostPort(u.Host)
   185  	if err != nil {
   186  		h = u.Host
   187  	}
   188  	if h == "" {
   189  		h = "localhost"
   190  	}
   191  	if p == "" {
   192  		p = "6379"
   193  	}
   194  	o.Addr = net.JoinHostPort(h, p)
   195  
   196  	f := strings.FieldsFunc(u.Path, func(r rune) bool {
   197  		return r == '/'
   198  	})
   199  	switch len(f) {
   200  	case 0:
   201  		o.DB = 0
   202  	case 1:
   203  		if o.DB, err = strconv.Atoi(f[0]); err != nil {
   204  			return nil, fmt.Errorf("invalid redis database number: %q", f[0])
   205  		}
   206  	default:
   207  		return nil, errors.New("invalid redis URL path: " + u.Path)
   208  	}
   209  
   210  	if u.Scheme == "rediss" {
   211  		o.TLSConfig = &tls.Config{ServerName: h}
   212  	}
   213  	return o, nil
   214  }
   215  
   216  func newConnPool(opt *Options) *pool.ConnPool {
   217  	return pool.NewConnPool(&pool.Options{
   218  		Dialer:             opt.Dialer,
   219  		PoolSize:           opt.PoolSize,
   220  		MinIdleConns:       opt.MinIdleConns,
   221  		MaxConnAge:         opt.MaxConnAge,
   222  		PoolTimeout:        opt.PoolTimeout,
   223  		IdleTimeout:        opt.IdleTimeout,
   224  		IdleCheckFrequency: opt.IdleCheckFrequency,
   225  	})
   226  }
   227  

View as plain text