mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-18 08:39:47 +01:00
7f8e3192cd
* Allow common redis and leveldb connections Prevents multiple reopening of redis and leveldb connections to the same place by sharing connections. Further allows for more configurable redis connection type using the redisURI and a leveldbURI scheme. Signed-off-by: Andrew Thornton <art27@cantab.net> * add unit-test Signed-off-by: Andrew Thornton <art27@cantab.net> * as per @lunny Signed-off-by: Andrew Thornton <art27@cantab.net> * add test Signed-off-by: Andrew Thornton <art27@cantab.net> * Update modules/cache/cache_redis.go * Update modules/queue/queue_disk.go * Update modules/cache/cache_redis.go * Update modules/cache/cache_redis.go * Update modules/queue/unique_queue_disk.go * Update modules/queue/queue_disk.go * Update modules/queue/unique_queue_disk.go * Update modules/session/redis.go Co-authored-by: techknowlogick <techknowlogick@gitea.io> Co-authored-by: Lauris BH <lauris@nix.lv>
198 lines
5.2 KiB
Go
Vendored
198 lines
5.2 KiB
Go
Vendored
package redis
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"net"
|
|
"time"
|
|
)
|
|
|
|
// UniversalOptions information is required by UniversalClient to establish
|
|
// connections.
|
|
type UniversalOptions struct {
|
|
// Either a single address or a seed list of host:port addresses
|
|
// of cluster/sentinel nodes.
|
|
Addrs []string
|
|
|
|
// Database to be selected after connecting to the server.
|
|
// Only single-node and failover clients.
|
|
DB int
|
|
|
|
// Common options.
|
|
|
|
Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
|
|
OnConnect func(*Conn) error
|
|
Username string
|
|
Password string
|
|
MaxRetries int
|
|
MinRetryBackoff time.Duration
|
|
MaxRetryBackoff time.Duration
|
|
DialTimeout time.Duration
|
|
ReadTimeout time.Duration
|
|
WriteTimeout time.Duration
|
|
PoolSize int
|
|
MinIdleConns int
|
|
MaxConnAge time.Duration
|
|
PoolTimeout time.Duration
|
|
IdleTimeout time.Duration
|
|
IdleCheckFrequency time.Duration
|
|
TLSConfig *tls.Config
|
|
|
|
// Only cluster clients.
|
|
|
|
MaxRedirects int
|
|
ReadOnly bool
|
|
RouteByLatency bool
|
|
RouteRandomly bool
|
|
|
|
// The sentinel master name.
|
|
// Only failover clients.
|
|
MasterName string
|
|
}
|
|
|
|
// Cluster returns cluster options created from the universal options.
|
|
func (o *UniversalOptions) Cluster() *ClusterOptions {
|
|
if len(o.Addrs) == 0 {
|
|
o.Addrs = []string{"127.0.0.1:6379"}
|
|
}
|
|
|
|
return &ClusterOptions{
|
|
Addrs: o.Addrs,
|
|
Dialer: o.Dialer,
|
|
OnConnect: o.OnConnect,
|
|
|
|
Username: o.Username,
|
|
Password: o.Password,
|
|
|
|
MaxRedirects: o.MaxRedirects,
|
|
ReadOnly: o.ReadOnly,
|
|
RouteByLatency: o.RouteByLatency,
|
|
RouteRandomly: o.RouteRandomly,
|
|
|
|
MaxRetries: o.MaxRetries,
|
|
MinRetryBackoff: o.MinRetryBackoff,
|
|
MaxRetryBackoff: o.MaxRetryBackoff,
|
|
|
|
DialTimeout: o.DialTimeout,
|
|
ReadTimeout: o.ReadTimeout,
|
|
WriteTimeout: o.WriteTimeout,
|
|
PoolSize: o.PoolSize,
|
|
MinIdleConns: o.MinIdleConns,
|
|
MaxConnAge: o.MaxConnAge,
|
|
PoolTimeout: o.PoolTimeout,
|
|
IdleTimeout: o.IdleTimeout,
|
|
IdleCheckFrequency: o.IdleCheckFrequency,
|
|
|
|
TLSConfig: o.TLSConfig,
|
|
}
|
|
}
|
|
|
|
// Failover returns failover options created from the universal options.
|
|
func (o *UniversalOptions) Failover() *FailoverOptions {
|
|
if len(o.Addrs) == 0 {
|
|
o.Addrs = []string{"127.0.0.1:26379"}
|
|
}
|
|
|
|
return &FailoverOptions{
|
|
SentinelAddrs: o.Addrs,
|
|
MasterName: o.MasterName,
|
|
|
|
Dialer: o.Dialer,
|
|
OnConnect: o.OnConnect,
|
|
|
|
DB: o.DB,
|
|
Username: o.Username,
|
|
Password: o.Password,
|
|
|
|
MaxRetries: o.MaxRetries,
|
|
MinRetryBackoff: o.MinRetryBackoff,
|
|
MaxRetryBackoff: o.MaxRetryBackoff,
|
|
|
|
DialTimeout: o.DialTimeout,
|
|
ReadTimeout: o.ReadTimeout,
|
|
WriteTimeout: o.WriteTimeout,
|
|
|
|
PoolSize: o.PoolSize,
|
|
MinIdleConns: o.MinIdleConns,
|
|
MaxConnAge: o.MaxConnAge,
|
|
PoolTimeout: o.PoolTimeout,
|
|
IdleTimeout: o.IdleTimeout,
|
|
IdleCheckFrequency: o.IdleCheckFrequency,
|
|
|
|
TLSConfig: o.TLSConfig,
|
|
}
|
|
}
|
|
|
|
// Simple returns basic options created from the universal options.
|
|
func (o *UniversalOptions) Simple() *Options {
|
|
addr := "127.0.0.1:6379"
|
|
if len(o.Addrs) > 0 {
|
|
addr = o.Addrs[0]
|
|
}
|
|
|
|
return &Options{
|
|
Addr: addr,
|
|
Dialer: o.Dialer,
|
|
OnConnect: o.OnConnect,
|
|
|
|
DB: o.DB,
|
|
Username: o.Username,
|
|
Password: o.Password,
|
|
|
|
MaxRetries: o.MaxRetries,
|
|
MinRetryBackoff: o.MinRetryBackoff,
|
|
MaxRetryBackoff: o.MaxRetryBackoff,
|
|
|
|
DialTimeout: o.DialTimeout,
|
|
ReadTimeout: o.ReadTimeout,
|
|
WriteTimeout: o.WriteTimeout,
|
|
|
|
PoolSize: o.PoolSize,
|
|
MinIdleConns: o.MinIdleConns,
|
|
MaxConnAge: o.MaxConnAge,
|
|
PoolTimeout: o.PoolTimeout,
|
|
IdleTimeout: o.IdleTimeout,
|
|
IdleCheckFrequency: o.IdleCheckFrequency,
|
|
|
|
TLSConfig: o.TLSConfig,
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
// UniversalClient is an abstract client which - based on the provided options -
|
|
// can connect to either clusters, or sentinel-backed failover instances
|
|
// or simple single-instance servers. This can be useful for testing
|
|
// cluster-specific applications locally.
|
|
type UniversalClient interface {
|
|
Cmdable
|
|
Context() context.Context
|
|
AddHook(Hook)
|
|
Watch(fn func(*Tx) error, keys ...string) error
|
|
Do(args ...interface{}) *Cmd
|
|
DoContext(ctx context.Context, args ...interface{}) *Cmd
|
|
Process(cmd Cmder) error
|
|
ProcessContext(ctx context.Context, cmd Cmder) error
|
|
Subscribe(channels ...string) *PubSub
|
|
PSubscribe(channels ...string) *PubSub
|
|
Close() error
|
|
}
|
|
|
|
var _ UniversalClient = (*Client)(nil)
|
|
var _ UniversalClient = (*ClusterClient)(nil)
|
|
var _ UniversalClient = (*Ring)(nil)
|
|
|
|
// NewUniversalClient returns a new multi client. The type of client returned depends
|
|
// on the following three conditions:
|
|
//
|
|
// 1. if a MasterName is passed a sentinel-backed FailoverClient will be returned
|
|
// 2. if the number of Addrs is two or more, a ClusterClient will be returned
|
|
// 3. otherwise, a single-node redis Client will be returned.
|
|
func NewUniversalClient(opts *UniversalOptions) UniversalClient {
|
|
if opts.MasterName != "" {
|
|
return NewFailoverClient(opts.Failover())
|
|
} else if len(opts.Addrs) > 1 {
|
|
return NewClusterClient(opts.Cluster())
|
|
}
|
|
return NewClient(opts.Simple())
|
|
}
|