Table of contents
Part of nurago, a collection of independent Go packages for backend services.
import "github.com/tecnickcom/nurago/pkg/redis"
Package redis wraps go-redis for key/value storage, Pub/Sub messaging, typed payload encoding, and connection health checks.
Redis reference: https://redis.io Underlying client: https://github.com/redis/go-redis
How It Works
New creates a Client given a SrvOptions (aliased from go-redis Options)
and a variadic list of Option values:
- The server address is validated before any network connection is attempted
(skipped when a client is injected via
WithRedisClient, since no connection is dialed). Both TCP host:port addresses and unix domain sockets are supported. - A go-redis client is constructed (or injected via
WithRedisClientfor tests). When at least one channel is declared withWithChannels, a Pub/Sub subscription feedsClient.ReceiveandClient.ReceiveDataone message per call. The subscription runs untilClient.Closeis called: canceling theNewcontext does not stop it. - Encode and decode functions (defaulting to
DefaultMessageEncodeFuncandDefaultMessageDecodeFunc) are stored on the client and used transparently by the typed data methods.
Operations
Client.Set,Client.Get, andClient.Delprovide raw key/value access with expiration.Client.SetDataandClient.GetDataencode and decode Go values with the configuredTEncodeFuncandTDecodeFunc.Client.SendandClient.Receivecarry raw strings;Client.SendDataandClient.ReceiveDataapply the same codec and return the channel name with the decoded value.WithMessageEncodeFuncandWithMessageDecodeFuncreplace the default codec.Client.HealthChecksends a PING and returns a wrapped error on failure.- A missing key surfaces as
ErrKeyNotFound; other configuration and subscription states surface as the exported Err values, all matchable with errors.Is. WithRedisClientinjects a customRClientfor testing.Client.Closereleases Pub/Sub and client resources; it is idempotent and required to stop the subscription when channels are configured.
Subscription Configuration
Use options to define Pub/Sub behavior at client creation time:
WithChannelsto subscribe to channels.WithChannelOptionsto tune subscription channel behavior: buffer size, send timeout, and health check interval. With the go-redis defaults, a consumer that stops callingClient.Receiveloses messages once the 100-message buffer stays full for one minute.
Usage
srv := &redis.SrvOptions{Addr: "localhost:6379"}
c, err := redis.New(ctx, srv, redis.WithChannels("events"))
if err != nil {
return err
}
defer c.Close()
if err := c.Set(ctx, "k", "v", 0); err != nil {
return err
}
if err := c.SendData(ctx, "events", event); err != nil {
return err
}
var event Event
channel, err := c.ReceiveData(ctx, &event)
if err != nil {
return err
}
if err := c.HealthCheck(ctx); err != nil {
return err
}
To swap in an encrypted codec, supply custom functions at construction time:
c, err := redis.New(ctx, srv,
redis.WithMessageEncodeFunc(myEncryptAndEncode),
redis.WithMessageDecodeFunc(myDecryptAndDecode),
)
When To Use
- You store structs and want serialization handled rather than written per call site.
- The same client should serve caching and Pub/Sub.
- Redis must be reported on the service health endpoint.
Example
client, err := redis.New(
context.TODO(),
nil,
redis.WithRedisClient(&exampleRClient{data: make(map[string]string)}),
)
if err != nil {
fmt.Println(err)
return
}
defer func() { _ = client.Close() }()
ctx := context.TODO()
err = client.Set(ctx, "greeting", "hello", time.Minute)
if err != nil {
fmt.Println(err)
return
}
var value string
err = client.Get(ctx, "greeting", &value)
fmt.Println(value, err)
fmt.Println(client.Del(ctx, "greeting"))
// Output:
// hello <nil>
// <nil>
Full source is in example_redis_test.go. More runnable examples are on pkg.go.dev.
Dependencies
Importing this package pulls 4 external modules:
github.com/cespare/xxhash/v2github.com/redis/go-redis/v9go.uber.org/atomicgolang.org/x/sys