Documentation
¶
Overview ¶
Package valkey solves the friction of integrating Valkey (https://valkey.io) — the open-source, Redis-compatible in-memory data store — into a Go service. The upstream valkey-go client (https://github.com/valkey-io/valkey-go) is powerful but low-level; this package wraps it with a clean, opinionated API that covers the most common patterns: key/value storage, typed data serialization, and Pub/Sub messaging, all behind a single Client type.
Problem ¶
Working directly with valkey-go requires composing command builders, type-asserting results, handling Pub/Sub subscriptions manually, and wiring in serialization for every call site. Teams end up duplicating the same thin adapter in every service. This package provides that adapter once, with consistent error wrapping, pluggable encode/decode functions, and a mockable interface for testing.
How It Works ¶
New creates a Client given a SrvOptions (aliased from valkey-go's ClientOption) 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 WithValkeyClient, since no connection is dialed).
- A valkey-go client is constructed (or injected via WithValkeyClient for tests). When at least one channel is declared with WithChannels, a pre-built, pinned Pub/Sub subscription command starts a background subscription that 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.
- 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 string 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 JSON+base64 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: WithValkeyClient injects a custom VKClient, enabling fast, dependency-free unit tests.
- Graceful close: Client.Close drains all pending calls before releasing the underlying connection. Close is required to stop the background subscription when channels are configured.
Usage ¶
srvOpts := valkey.SrvOptions{InitAddress: []string{"localhost:6379"}}
client, err := valkey.New(
ctx,
srvOpts,
valkey.WithChannels("events", "notifications"),
)
if err != nil {
return err
}
defer client.Close()
// Store and retrieve a typed value:
type Payload struct{ Message string }
if err := client.SetData(ctx, "my-key", Payload{"hello"}, time.Hour); err != nil {
return err
}
var p Payload
if err := client.GetData(ctx, "my-key", &p); err != nil {
return err
}
// Publish and consume a typed message:
if err := client.SendData(ctx, "events", Payload{"fired"}); err != nil {
return err
}
var event Payload
channel, err := client.ReceiveData(ctx, &event)
To swap in an encrypted codec, supply custom functions at construction time:
client, err := valkey.New(ctx, srvOpts,
valkey.WithMessageEncodeFunc(myEncryptAndEncode),
valkey.WithMessageDecodeFunc(myDecryptAndDecode),
)
Index ¶
- Variables
- func DefaultMessageDecodeFunc(_ context.Context, msg string, data any) error
- func DefaultMessageEncodeFunc(_ context.Context, data any) (string, error)
- func MessageDecode(msg string, data any) error
- func MessageEncode(data any) (string, error)
- type Client
- func (c *Client) Close()
- func (c *Client) Del(ctx context.Context, key string) error
- func (c *Client) Get(ctx context.Context, key string) (string, error)
- func (c *Client) GetData(ctx context.Context, key string, data any) error
- func (c *Client) HealthCheck(ctx context.Context) error
- func (c *Client) Receive(ctx context.Context) (string, string, error)
- func (c *Client) ReceiveData(ctx context.Context, data any) (string, error)
- func (c *Client) Send(ctx context.Context, channel string, message string) error
- func (c *Client) SendData(ctx context.Context, channel string, data any) error
- func (c *Client) Set(ctx context.Context, key string, value string, exp time.Duration) error
- func (c *Client) SetData(ctx context.Context, key string, data any, exp time.Duration) error
- type Option
- type SrvOptions
- type TDecodeFunc
- type TEncodeFunc
- type VKClient
- type VKMessage
- type VKPubSub
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalidOptions is returned by New when no client is injected and the // server options carry a missing or malformed InitAddress. ErrInvalidOptions = errors.New("valkey: missing or invalid client options") // ErrNilEncodeFunc is returned by New when the message encode function is nil. ErrNilEncodeFunc = errors.New("valkey: nil message encode function") // ErrNilDecodeFunc is returned by New when the message decode function is nil. ErrNilDecodeFunc = errors.New("valkey: nil message decode function") // ErrInvalidChannelName is returned by New when a subscription channel // name configured via WithChannels is empty. ErrInvalidChannelName = errors.New("valkey: 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("valkey: key not found") // ErrNoSubscription is returned by Receive and ReceiveData when the client // was constructed without any subscription channel (see WithChannels). ErrNoSubscription = errors.New("valkey: no subscription channel configured") // ErrSubscriptionClosed is returned by Receive and ReceiveData after the // background subscription has ended cleanly (e.g. on Close). ErrSubscriptionClosed = errors.New("valkey: subscription closed") )
Sentinel errors returned by the package. They can be matched with errors.Is so callers can distinguish configuration problems from subscription state.
Functions ¶
func DefaultMessageDecodeFunc ¶
DefaultMessageDecodeFunc provides default decoding used by ReceiveData.
func DefaultMessageEncodeFunc ¶
DefaultMessageEncodeFunc provides default encoding used by SendData.
func MessageDecode ¶
MessageDecode decodes a MessageEncode payload into data, which must be a pointer.
func MessageEncode ¶
MessageEncode encodes and serializes data into a string payload.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client wraps Valkey KV/PubSub operations with optional typed payload codecs.
func New ¶
New constructs a Valkey client wrapper with optional pinned Pub/Sub subscription and pluggable codecs.
A Pub/Sub subscription is established only when at least one channel is configured via WithChannels: a single background goroutine then receives the published messages and hands them over, one per call, to Receive or ReceiveData.
ctx does not bound the lifetime of the client or the subscription. It contributes only context values to the subscription and is unused entirely when no channels are configured. Canceling ctx after New returns does not stop the subscription — it runs until Close is called or the server disconnects. Consequently, when channels are configured, Close is the only way to stop the background goroutine and must be called.
func (*Client) Close ¶
func (c *Client) Close()
Close stops the Pub/Sub subscription (when configured) and closes the underlying client after pending calls complete. It is safe to call Close multiple times; only the first call releases the underlying client.
When channels are configured, Close must be called to stop the background subscription goroutine and release its resources: canceling the context passed to New does not.
func (*Client) Get ¶
Get retrieves the raw string value for key.
When the key does not exist, the returned error satisfies errors.Is(err, ErrKeyNotFound).
func (*Client) GetData ¶
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 ¶
HealthCheck verifies Valkey connectivity with a PING command.
func (*Client) Receive ¶
Receive returns the next raw Pub/Sub message as channel name and payload.
Messages are delivered by the background subscription established at construction time; each call consumes exactly one message. 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, ErrSubscriptionClosed when the subscription has ended cleanly (e.g. on Close), and a wrapped subscription error when it terminated due to a failure. Match the sentinel errors with errors.Is.
func (*Client) ReceiveData ¶
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) Set ¶
Set stores a raw string value for key with expiration.
A non-positive exp stores the key without expiration (no TTL). Whole-second durations are sent as EX (seconds), while other durations use PX (milliseconds) for sub-second precision, with a minimum effective TTL of one millisecond.
type Option ¶
type Option func(*cfg)
Option customizes client configuration.
func WithChannels ¶
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 WithValkeyClient ¶
WithValkeyClient injects an existing Valkey client, primarily for testing.
type SrvOptions ¶
type SrvOptions = libvalkey.ClientOption
SrvOptions aliases valkey-go client options used when constructing a client.
type TDecodeFunc ¶
TDecodeFunc is the type of function used to replace the default message decoding function used by ReceiveData() and GetData().
type TEncodeFunc ¶
TEncodeFunc is the type of function used to replace the default message encoding function used by SendData() and SetData().
type VKMessage ¶
type VKMessage = libvalkey.PubSubMessage
VKMessage aliases a valkey-go Pub/Sub message.