redis

package
v1.148.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 11, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package redis provides focused helpers built on go-redis for common application workflows: key/value storage, Pub/Sub messaging, typed payload encoding, and basic connection health checks.

Redis reference: https://redis.io Underlying client: https://github.com/redis/go-redis

Problem

Direct use of go-redis is powerful but often leads to repeated adapter code in services: typed payload serialization, subscription channel wiring, and consistent error wrapping around set/get/publish operations. This package centralizes those patterns behind a minimal client API.

How It Works

New creates a Client given a SrvOptions (aliased from go-redis Options) and a variadic list of Option values:

  1. 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.
  2. A go-redis client is constructed (or injected via WithRedisClient for tests). When at least one channel is declared with WithChannels, a Pub/Sub subscription feeds Client.Receive and Client.ReceiveData one message per call. The subscription runs until Client.Close is called: canceling the New context does not stop it.
  3. Encode and decode functions — defaulting to DefaultMessageEncodeFunc and DefaultMessageDecodeFunc — are stored on the client and used transparently by the typed data methods.

Key Features

  • Raw operations: Client.Set, Client.Get, and Client.Del offer direct key/value access with expiration support.
  • Typed data operations: Client.SetData and Client.GetData encode/decode Go values automatically using the configured TEncodeFunc / TDecodeFunc, removing serialization boilerplate at every call site.
  • Pub/Sub: Client.Send and Client.Receive work with raw strings; Client.SendData and Client.ReceiveData apply the same encode/decode pipeline, returning the channel name alongside the decoded value.
  • Pluggable serialization: WithMessageEncodeFunc and WithMessageDecodeFunc replace the default codec with any implementation — including encrypted or compressed payloads — without changing call sites.
  • Health check: Client.HealthCheck sends a PING and returns a wrapped error on failure, making it trivial to integrate with liveness probes.
  • Sentinel errors: a missing key surfaces as ErrKeyNotFound, and configuration or subscription states as the other exported Err values, all matchable with errors.Is.
  • Mockable client: WithRedisClient injects a custom RClient, enabling fast, dependency-free unit tests of the command path.
  • Graceful close: Client.Close releases 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:

  • WithChannels to subscribe to channels.
  • WithChannelOptions to tune subscription channel behavior: buffer size, send timeout, and health check interval. Note that with the go-redis defaults, a consumer that stops calling Client.Receive loses 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),
)

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidOptions is returned by New when no client is injected and the
	// server options carry a missing or malformed address.
	ErrInvalidOptions = errors.New("redis: missing or invalid client options")

	// ErrNilEncodeFunc is returned by New when the message encode function is nil.
	ErrNilEncodeFunc = errors.New("redis: nil message encode function")

	// ErrNilDecodeFunc is returned by New when the message decode function is nil.
	ErrNilDecodeFunc = errors.New("redis: nil message decode function")

	// ErrInvalidChannelName is returned by New when a subscription channel
	// name configured via WithChannels is empty.
	ErrInvalidChannelName = errors.New("redis: empty subscription channel name")

	// ErrKeyNotFound is returned by Get and GetData when the key does not
	// exist in the datastore. It signals a missing lookup target (e.g. maps
	// to HTTP 404) rather than a connection or protocol failure.
	ErrKeyNotFound = errors.New("redis: key not found")

	// ErrNoSubscription is returned by Receive and ReceiveData when the client
	// was constructed without any subscription channel (see WithChannels).
	ErrNoSubscription = errors.New("redis: no subscription channel configured")

	// ErrSubscriptionClosed is returned by Receive and ReceiveData after the
	// subscription message channel has been closed (e.g. on Close).
	ErrSubscriptionClosed = errors.New("redis: subscription closed")
)

Sentinel errors returned by the package. They can be matched with errors.Is so callers can distinguish configuration problems from lookup and subscription states.

Functions

func DefaultMessageDecodeFunc

func DefaultMessageDecodeFunc(_ context.Context, msg string, data any) error

DefaultMessageDecodeFunc provides default decoding used by ReceiveData.

func DefaultMessageEncodeFunc

func DefaultMessageEncodeFunc(_ context.Context, data any) (string, error)

DefaultMessageEncodeFunc provides default encoding used by SendData.

func MessageDecode

func MessageDecode(msg string, data any) error

MessageDecode decodes a MessageEncode payload into data, which must be a pointer.

func MessageEncode

func MessageEncode(data any) (string, error)

MessageEncode encodes and serializes data into a string payload.

Types

type ChannelOption

type ChannelOption = libredis.ChannelOption

ChannelOption aliases go-redis Pub/Sub channel options.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client wraps Redis KV/PubSub operations with optional typed payload codecs.

func New

func New(ctx context.Context, srvopt *SrvOptions, opts ...Option) (*Client, error)

New constructs a Redis client wrapper with optional Pub/Sub subscriptions and pluggable message codecs.

A Pub/Sub subscription is established only when at least one channel is configured via WithChannels; otherwise no subscription resources are allocated.

ctx does not bound the lifetime of the client or the subscription: go-redis uses it only for the initial SUBSCRIBE command (whose failure surfaces through the subscription retry loop, not here) while the goroutine delivering messages to Receive runs until Close is called. Consequently, when channels are configured, Close is the only way to stop the subscription and must be called.

func (*Client) Close

func (c *Client) Close() error

Close gracefully closes Pub/Sub and Redis client resources.

When no Pub/Sub subscription was configured at construction time, only the Redis client is closed. The Redis client is always closed even when closing the Pub/Sub subscription fails; in that case the errors are joined.

Close is idempotent: only the first call releases the resources, and every subsequent call returns the result of the first. When channels are configured, Close must be called to stop the background subscription: canceling the context passed to New does not.

func (*Client) Del

func (c *Client) Del(ctx context.Context, key string) error

Del deletes key from the datastore.

func (*Client) Get

func (c *Client) Get(ctx context.Context, key string, value any) error

Get retrieves the raw value of key and scans it into value.

value must be a pointer to a type supported by go-redis scanning: a string, a numeric or bool type, time.Time, time.Duration, []byte, or a type implementing encoding.BinaryUnmarshaler. Use GetData for values stored with SetData.

When the key does not exist, the returned error satisfies errors.Is(err, ErrKeyNotFound).

func (*Client) GetData

func (c *Client) GetData(ctx context.Context, key string, data any) error

GetData retrieves an encoded value from key and decodes it into data.

When the key does not exist, the returned error satisfies errors.Is(err, ErrKeyNotFound).

func (*Client) HealthCheck

func (c *Client) HealthCheck(ctx context.Context) error

HealthCheck verifies Redis connectivity with a PING command.

func (*Client) Receive

func (c *Client) Receive(ctx context.Context) (string, string, error)

Receive returns the next raw message from subscribed channels as channel name and payload.

Each call consumes exactly one message delivered by the subscription established at construction time. It returns ErrNoSubscription when the client was constructed without any subscription channel (see WithChannels), a wrapped ctx.Err() when ctx is canceled or its deadline expires, and ErrSubscriptionClosed after Close. Match the sentinel errors with errors.Is. After Close, any messages already buffered are still delivered before ErrSubscriptionClosed is returned.

Messages are buffered in a Go channel holding 100 messages by default; when the buffer stays full for one minute (the go-redis default send timeout), the incoming message is silently dropped and only logged by go-redis. Slow consumers should tune this via WithChannelOptions (libredis.WithChannelSize, libredis.WithChannelSendTimeout).

func (*Client) ReceiveData

func (c *Client) ReceiveData(ctx context.Context, data any) (string, error)

ReceiveData receives an encoded message, decodes it into data, and returns the source channel. On any error, including a decode failure, the returned channel name is empty.

func (*Client) Send

func (c *Client) Send(ctx context.Context, channel string, message any) error

Send publishes a raw value to channel.

message must be a type supported by the go-redis protocol writer (see Set); use SendData for arbitrary values.

func (*Client) SendData

func (c *Client) SendData(ctx context.Context, channel string, data any) error

SendData encodes data and publishes it to channel.

func (*Client) Set

func (c *Client) Set(ctx context.Context, key string, value any, exp time.Duration) error

Set stores a raw value for key with expiration.

value must be a type supported by the go-redis protocol writer: a string, []byte, a numeric or bool type (or a pointer to one), time.Time, time.Duration, or a type implementing encoding.BinaryMarshaler; anything else fails at command time. Use SetData for arbitrary values.

A zero or negative exp (other than libredis.KeepTTL, which retains the key's existing TTL) stores the key without expiration. Positive durations below one millisecond are truncated to 1ms by go-redis.

func (*Client) SetData

func (c *Client) SetData(ctx context.Context, key string, data any, exp time.Duration) error

SetData encodes data and stores it at key with expiration.

A zero or negative exp (other than libredis.KeepTTL, which retains the key's existing TTL) stores the key without expiration. Positive durations below one millisecond are truncated to 1ms by go-redis.

type Option

type Option func(*cfg)

Option customizes client configuration.

func WithChannelOptions

func WithChannelOptions(opts ...ChannelOption) Option

WithChannelOptions sets subscription channel options for go-redis Pub/Sub (e.g. libredis.WithChannelSize, libredis.WithChannelSendTimeout, libredis.WithChannelHealthCheckInterval). It has no effect unless WithChannels configures at least one channel.

func WithChannels

func WithChannels(channels ...string) Option

WithChannels sets Pub/Sub channels subscribed at client creation time.

func WithMessageDecodeFunc

func WithMessageDecodeFunc(f TDecodeFunc) Option

WithMessageDecodeFunc overrides the decoder used by ReceiveData and GetData.

func WithMessageEncodeFunc

func WithMessageEncodeFunc(f TEncodeFunc) Option

WithMessageEncodeFunc overrides the encoder used by SendData and SetData.

func WithRedisClient

func WithRedisClient(rclient RClient) Option

WithRedisClient injects an existing go-redis client, primarily for testing.

When a client is injected, the server options passed to New are never consulted and their address is not validated. Injection is intended for command-path testing: Get, Set, Del, Publish, and Ping results can be built with the public go-redis constructors (libredis.NewStringResult and friends). Combining an injected client with WithChannels requires its Subscribe to return a functional *libredis.PubSub, so subscription flows are better tested against a real server.

type RClient

type RClient interface {
	Close() error
	Del(ctx context.Context, keys ...string) *libredis.IntCmd
	Get(ctx context.Context, key string) *libredis.StringCmd

	// Ping is used by HealthCheck.
	Ping(ctx context.Context) *libredis.StatusCmd

	Publish(ctx context.Context, channel string, message any) *libredis.IntCmd
	Set(ctx context.Context, key string, value any, expiration time.Duration) *libredis.StatusCmd
	Subscribe(ctx context.Context, channels ...string) *libredis.PubSub
}

RClient defines the go-redis client calls used by Client.

type RMessage

type RMessage = libredis.Message

RMessage aliases a go-redis Pub/Sub message.

type RPubSub

type RPubSub interface {
	Channel(opts ...libredis.ChannelOption) <-chan *libredis.Message
	Close() error
}

RPubSub defines the go-redis Pub/Sub calls used by Client.

type SrvOptions

type SrvOptions = libredis.Options

SrvOptions aliases go-redis client options used when constructing a client.

type TDecodeFunc

type TDecodeFunc func(ctx context.Context, msg string, data any) error

TDecodeFunc is the type of function used to replace the default message decoding function used by ReceiveData() and GetData().

type TEncodeFunc

type TEncodeFunc func(ctx context.Context, data any) (string, error)

TEncodeFunc is the type of function used to replace the default message encoding function used by SendData() and SetData().

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL