feat: extract dialer to `DefaultDialer` to allow wrapping

Allowing the default dialing function to be wrapped allows for library
users to let the library continue to own the logic for dialing and let
users wrap the function for more observability.

My use case is to override `Options.Dialer` and add Jaeger tracing to
gain insight into the cost of new connections on a latency sensitive API.

```go
	defDialer := redis.DefaultDialer(opts)
	opts.Dialer = func(ctx context.Context, network, addr string) (net.Conn, error) {
		span, ctx := opentracing.StartSpanFromContext(ctx, "cache-repo-redis: new redis connection")
		defer span.Finish()

		return defDialer(ctx, network, addr)
	}
```

Without this, I end up needing to copy-paste the code from the internal
code, which is less-than-ideal since I don't want to own the maintenance
of this logic.
This commit is contained in:
nick comer 2022-01-14 16:01:09 -05:00
parent f1dd3d5898
commit 52276c393d
1 changed files with 16 additions and 10 deletions

View File

@ -129,16 +129,7 @@ func (opt *Options) init() {
opt.DialTimeout = 5 * time.Second opt.DialTimeout = 5 * time.Second
} }
if opt.Dialer == nil { if opt.Dialer == nil {
opt.Dialer = func(ctx context.Context, network, addr string) (net.Conn, error) { opt.Dialer = DefaultDialer(opt)
netDialer := &net.Dialer{
Timeout: opt.DialTimeout,
KeepAlive: 5 * time.Minute,
}
if opt.TLSConfig == nil {
return netDialer.DialContext(ctx, network, addr)
}
return tls.DialWithDialer(netDialer, network, addr, opt.TLSConfig)
}
} }
if opt.PoolSize == 0 { if opt.PoolSize == 0 {
opt.PoolSize = 10 * runtime.GOMAXPROCS(0) opt.PoolSize = 10 * runtime.GOMAXPROCS(0)
@ -189,6 +180,21 @@ func (opt *Options) clone() *Options {
return &clone return &clone
} }
// DefaultDialer returns a function that will be used as the default dialer
// when none is specified in Options.Dialer.
func DefaultDialer(opt *Options) func(context.Context, string, string) (net.Conn, error) {
return func(ctx context.Context, network, addr string) (net.Conn, error) {
netDialer := &net.Dialer{
Timeout: opt.DialTimeout,
KeepAlive: 5 * time.Minute,
}
if opt.TLSConfig == nil {
return netDialer.DialContext(ctx, network, addr)
}
return tls.DialWithDialer(netDialer, network, addr, opt.TLSConfig)
}
}
// ParseURL parses an URL into Options that can be used to connect to Redis. // ParseURL parses an URL into Options that can be used to connect to Redis.
// Scheme is required. // Scheme is required.
// There are two connection types: by tcp socket and by unix socket. // There are two connection types: by tcp socket and by unix socket.