valkey

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 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:

  1. The server address is validated before any network connection is attempted (skipped when a client is injected via WithValkeyClient, since no connection is dialed).
  2. 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.
  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 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

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 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

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 Client

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

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

func New

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

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) 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) (string, error)

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

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 Valkey connectivity with a PING command.

func (*Client) Receive

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

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

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 string) error

Send publishes a raw string message to channel.

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 string, exp time.Duration) error

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.

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.

type Option

type Option func(*cfg)

Option customizes client configuration.

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 WithValkeyClient

func WithValkeyClient(vkclient VKClient) Option

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

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().

type VKClient

type VKClient = libvalkey.Client

VKClient aliases the valkey-go client interface used by Client.

type VKMessage

type VKMessage = libvalkey.PubSubMessage

VKMessage aliases a valkey-go Pub/Sub message.

type VKPubSub

type VKPubSub = libvalkey.Completed

VKPubSub aliases the valkey-go completed Pub/Sub command type used by Client.

Jump to

Keyboard shortcuts

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