universal.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package redis
  2. import (
  3. "crypto/tls"
  4. "time"
  5. )
  6. // UniversalOptions information is required by UniversalClient to establish
  7. // connections.
  8. type UniversalOptions struct {
  9. // Either a single address or a seed list of host:port addresses
  10. // of cluster/sentinel nodes.
  11. Addrs []string
  12. // The sentinel master name.
  13. // Only failover clients.
  14. MasterName string
  15. // Database to be selected after connecting to the server.
  16. // Only single-node and failover clients.
  17. DB int
  18. // Only cluster clients.
  19. // Enables read only queries on slave nodes.
  20. ReadOnly bool
  21. MaxRedirects int
  22. RouteByLatency bool
  23. // Common options
  24. OnConnect func(*Conn) error
  25. MaxRetries int
  26. Password string
  27. DialTimeout time.Duration
  28. ReadTimeout time.Duration
  29. WriteTimeout time.Duration
  30. PoolSize int
  31. PoolTimeout time.Duration
  32. IdleTimeout time.Duration
  33. IdleCheckFrequency time.Duration
  34. TLSConfig *tls.Config
  35. }
  36. func (o *UniversalOptions) cluster() *ClusterOptions {
  37. if len(o.Addrs) == 0 {
  38. o.Addrs = []string{"127.0.0.1:6379"}
  39. }
  40. return &ClusterOptions{
  41. Addrs: o.Addrs,
  42. MaxRedirects: o.MaxRedirects,
  43. RouteByLatency: o.RouteByLatency,
  44. ReadOnly: o.ReadOnly,
  45. OnConnect: o.OnConnect,
  46. MaxRetries: o.MaxRetries,
  47. Password: o.Password,
  48. DialTimeout: o.DialTimeout,
  49. ReadTimeout: o.ReadTimeout,
  50. WriteTimeout: o.WriteTimeout,
  51. PoolSize: o.PoolSize,
  52. PoolTimeout: o.PoolTimeout,
  53. IdleTimeout: o.IdleTimeout,
  54. IdleCheckFrequency: o.IdleCheckFrequency,
  55. TLSConfig: o.TLSConfig,
  56. }
  57. }
  58. func (o *UniversalOptions) failover() *FailoverOptions {
  59. if len(o.Addrs) == 0 {
  60. o.Addrs = []string{"127.0.0.1:26379"}
  61. }
  62. return &FailoverOptions{
  63. SentinelAddrs: o.Addrs,
  64. MasterName: o.MasterName,
  65. DB: o.DB,
  66. OnConnect: o.OnConnect,
  67. MaxRetries: o.MaxRetries,
  68. Password: o.Password,
  69. DialTimeout: o.DialTimeout,
  70. ReadTimeout: o.ReadTimeout,
  71. WriteTimeout: o.WriteTimeout,
  72. PoolSize: o.PoolSize,
  73. PoolTimeout: o.PoolTimeout,
  74. IdleTimeout: o.IdleTimeout,
  75. IdleCheckFrequency: o.IdleCheckFrequency,
  76. TLSConfig: o.TLSConfig,
  77. }
  78. }
  79. func (o *UniversalOptions) simple() *Options {
  80. addr := "127.0.0.1:6379"
  81. if len(o.Addrs) > 0 {
  82. addr = o.Addrs[0]
  83. }
  84. return &Options{
  85. Addr: addr,
  86. DB: o.DB,
  87. OnConnect: o.OnConnect,
  88. MaxRetries: o.MaxRetries,
  89. Password: o.Password,
  90. DialTimeout: o.DialTimeout,
  91. ReadTimeout: o.ReadTimeout,
  92. WriteTimeout: o.WriteTimeout,
  93. PoolSize: o.PoolSize,
  94. PoolTimeout: o.PoolTimeout,
  95. IdleTimeout: o.IdleTimeout,
  96. IdleCheckFrequency: o.IdleCheckFrequency,
  97. TLSConfig: o.TLSConfig,
  98. }
  99. }
  100. // --------------------------------------------------------------------
  101. // UniversalClient is an abstract client which - based on the provided options -
  102. // can connect to either clusters, or sentinel-backed failover instances or simple
  103. // single-instance servers. This can be useful for testing cluster-specific
  104. // applications locally.
  105. type UniversalClient interface {
  106. Cmdable
  107. Watch(fn func(*Tx) error, keys ...string) error
  108. Process(cmd Cmder) error
  109. WrapProcess(fn func(oldProcess func(cmd Cmder) error) func(cmd Cmder) error)
  110. Subscribe(channels ...string) *PubSub
  111. PSubscribe(channels ...string) *PubSub
  112. Close() error
  113. }
  114. var _ UniversalClient = (*Client)(nil)
  115. var _ UniversalClient = (*ClusterClient)(nil)
  116. // NewUniversalClient returns a new multi client. The type of client returned depends
  117. // on the following three conditions:
  118. //
  119. // 1. if a MasterName is passed a sentinel-backed FailoverClient will be returned
  120. // 2. if the number of Addrs is two or more, a ClusterClient will be returned
  121. // 3. otherwise, a single-node redis Client will be returned.
  122. func NewUniversalClient(opts *UniversalOptions) UniversalClient {
  123. if opts.MasterName != "" {
  124. return NewFailoverClient(opts.failover())
  125. } else if len(opts.Addrs) > 1 {
  126. return NewClusterClient(opts.cluster())
  127. }
  128. return NewClient(opts.simple())
  129. }