Skip to content

Commit 3d299a3

Browse files
authored
Add Redis TLS server name and cluster mode support (#522)
- Add set_tls_server_name to override the TLS server name (SNI) on the Redis client connection. - Add cluster_mode to run the producer against a Redis Cluster. - Include vin and tx_type in Redis publish-error logs.
1 parent c4c2f08 commit 3d299a3

2 files changed

Lines changed: 40 additions & 9 deletions

File tree

config/config.go

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import (
77
_ "embed" //Used for default CAs
88
"errors"
99
"fmt"
10+
"net"
1011
"net/http"
12+
"net/url"
1113
"os"
1214
"strings"
1315
"time"
@@ -155,13 +157,15 @@ type Kinesis struct {
155157

156158
// Redis is a configuration for the Redis pub/sub producer.
157159
type Redis struct {
158-
Addrs []string `json:"addrs"`
159-
Username string `json:"username,omitempty"`
160-
Password string `json:"password,omitempty"`
161-
DB int `json:"db,omitempty"`
162-
TLS *TLS `json:"tls,omitempty"`
163-
Pool *RedisPool `json:"pool,omitempty"`
164-
PublishTimeout time.Duration `json:"publish_timeout,omitempty"`
160+
Addrs []string `json:"addrs"`
161+
Username string `json:"username,omitempty"`
162+
Password string `json:"password,omitempty"`
163+
DB int `json:"db,omitempty"`
164+
TLS *TLS `json:"tls,omitempty"`
165+
OverrideTLSServerName bool `json:"override_tls_server_name,omitempty"`
166+
Pool *RedisPool `json:"pool,omitempty"`
167+
PublishTimeout time.Duration `json:"publish_timeout,omitempty"`
168+
ClusterMode bool `json:"cluster_mode,omitempty"`
165169

166170
// PublishVINTopics, when true, always publishes on the VIN set-key
167171
// channel.
@@ -191,6 +195,9 @@ func (r *Redis) options() (*goredis.UniversalOptions, error) {
191195
if err != nil {
192196
return nil, err
193197
}
198+
if r.OverrideTLSServerName && tlsConfig != nil {
199+
tlsConfig.ServerName = r.getServerName()
200+
}
194201
password := r.Password
195202
if envPassword := os.Getenv("REDIS_PASSWORD"); envPassword != "" {
196203
password = envPassword
@@ -203,6 +210,9 @@ func (r *Redis) options() (*goredis.UniversalOptions, error) {
203210
DB: r.DB,
204211
TLSConfig: tlsConfig,
205212
}
213+
if r.ClusterMode {
214+
options.IsClusterMode = true
215+
}
206216
if r.Pool != nil {
207217
options.PoolSize = r.Pool.PoolSize
208218
options.MinIdleConns = r.Pool.MinIdleConns
@@ -217,6 +227,24 @@ func (r *Redis) options() (*goredis.UniversalOptions, error) {
217227
return options, nil
218228
}
219229

230+
func (r *Redis) getServerName() string {
231+
if len(r.Addrs) == 0 {
232+
return ""
233+
}
234+
235+
addr := r.Addrs[0]
236+
// A scheme-qualified addr (e.g. rediss://host:6379) parses cleanly here.
237+
if parsedURL, err := url.Parse(addr); err == nil && parsedURL.Hostname() != "" {
238+
return parsedURL.Hostname()
239+
}
240+
// A bare host:port (the common case) is mis-parsed by url.Parse as
241+
// scheme:opaque, so strip the port directly.
242+
if host, _, err := net.SplitHostPort(addr); err == nil {
243+
return host
244+
}
245+
return addr
246+
}
247+
220248
//go:embed files/eng_ca.crt
221249
var defaultEngCA []byte
222250

datastore/redis/redis.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ func NewProducer(options *redis.UniversalOptions, publishTimeout time.Duration,
8686
timeout: timeout,
8787
}
8888

89+
if err := client.Ping(context.Background()).Err(); err != nil {
90+
return nil, fmt.Errorf("redis_connect_error %w", err)
91+
}
8992
producer.logger.ActivityLog("redis_registered", logrus.LogInfo{"namespace": namespace, "publish_vin_topics": publishVINTopics, "subscriber_set_prefix": subscriberSetPrefix})
9093
return producer, nil
9194
}
@@ -97,15 +100,15 @@ func (p *Producer) Produce(entry *telemetry.Record) {
97100
payload := entry.Payload()
98101
channels, err := p.channelsForRecord(entry)
99102
if err != nil {
100-
p.ReportError("redis_err", err, logrus.LogInfo{"channel": "", "txid": entry.Txid})
103+
p.ReportError("redis_err", err, logrus.LogInfo{"vin": entry.Vin, "tx_type": entry.TxType, "txid": entry.Txid})
101104
metricsRegistry.errorCount.Inc(map[string]string{"record_type": entry.TxType})
102105
return
103106
}
104107
for _, channel := range channels {
105108
ctx, cancel := context.WithTimeout(context.Background(), p.timeout)
106109
defer cancel()
107110
if err := p.client.Publish(ctx, channel, payload).Err(); err != nil {
108-
p.ReportError("redis_err", err, logrus.LogInfo{"channel": channel, "txid": entry.Txid})
111+
p.ReportError("redis_err", err, logrus.LogInfo{"channel": channel, "vin": entry.Vin, "tx_type": entry.TxType, "txid": entry.Txid})
109112
metricsRegistry.errorCount.Inc(map[string]string{"record_type": entry.TxType})
110113
return
111114
}

0 commit comments

Comments
 (0)