redis

package
v1.8.1 Latest Latest
Warning

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

Go to latest
Published: Jun 23, 2026 License: MIT Imports: 9 Imported by: 0

README

redis

Wrapper around github.com/redis/go-redis/v9 that adds a lifecycle contract: Shutdown(ctx), Healthcheck(ctx), opt-in OpenTelemetry instrumentation, and an Unwrap() accessor for power users.

Includes Shutdown(ctx) for proper connection pool cleanup and Healthcheck(ctx) for readiness probes.

When to use

Any service that needs Redis: caching, session storage, rate limiting, pubsub fan-out, distributed locks. The convenience methods cover Get/Set/Del; for everything else, use Unwrap().

Quickstart

package main

import (
    "context"
    "log"

    "github.com/sergeyslonimsky/core/app"
    "github.com/sergeyslonimsky/core/redis"
)

func main() {
    ctx := context.Background()

    client, err := redis.New(ctx, redis.Config{
        Host: "localhost",
        Port: "6379",
    },
        redis.WithOtel(),
        redis.WithPoolSize(50),
    )
    if err != nil {
        log.Fatal(err)
    }

    a := app.New()
    a.Add(client)  // registers Shutdown + Healthcheck

    // ... use client.Get/Set/Del or client.Unwrap() inside your handlers
}

Configuration

type Config struct {
    Host     string  // Required
    Port     string  // Required
    Password string  // Optional
    DB       int     // Optional, default 0
}

App-level mapping example:

redis.Config{
    Host:     raw.GetString("redis.host"),
    Port:     raw.GetString("redis.port"),
    Password: raw.GetString("redis.password"),
    DB:       raw.GetInt("redis.db"),
}

Options

  • WithLogger(*slog.Logger) — used for lifecycle events. Default: slog.Default().
  • WithPoolSize(n int) — connection pool size. Default: go-redis chooses 10*runtime.NumCPU().
  • WithReadTimeout(time.Duration) — per-command read timeout. Default: 3s (go-redis).
  • WithWriteTimeout(time.Duration) — per-command write timeout. Default: same as ReadTimeout.
  • WithOtel() — instrument every command with OpenTelemetry traces and metrics via redisotel.

Observability (WithOtel)

Calls redisotel.InstrumentTracing(client) and redisotel.InstrumentMetrics(client) from github.com/redis/go-redis/extra/redisotel/v9. Uses the global tracer/meter providers — call otel.Setup and register the provider with app.App before constructing the client.

One span per command is created with the command name, key (where applicable), and result/error. Pool metrics (active connections, hits, misses) are reported via the meter provider.

Lifecycle

*Client implements lifecycle.Resource + lifecycle.Healthchecker. Register with app.App.Add(client). Recommended ordering inside the resource list:

a.Add(otelProvider)  // first → shuts down last
a.Add(db)            // before redis
a.Add(redisClient)   // before HTTP/gRPC servers
a.Add(httpServer)    // last → shuts down first

Shutdown calls the underlying *redis.Client.Close(). The ctx parameter is ignored (go-redis's Close is synchronous).

Healthcheck issues a single PING and returns the error if the command fails or the deadline expires.

Extending

rc := client.Unwrap()
pipe := rc.Pipeline()
// ... pipelines, scripts, pubsub, transactions

The returned *redis.Client is owned by the wrapper. Don't call Close() on it directly — always go through Shutdown.

Testing

For unit tests, use an in-memory fake like miniredis:

import "github.com/alicebob/miniredis/v2"

mr := miniredis.RunT(t)
client, err := redis.New(ctx, redis.Config{
    Host: mr.Host(),
    Port: mr.Port(),
})

See also

Documentation

Overview

Package redis wraps github.com/redis/go-redis/v9 with the lifecycle contract used across core: a typed Config, functional Options, and Shutdown / Healthcheck methods so a Client can be registered with app.App.

The Client is a lifecycle.Resource (not a Runner) — its only background work is the connection pool maintained by go-redis, which is an implementation detail. Callers use the typed Get/Set/Del helpers or call Unwrap to access the underlying *redis.Client for advanced operations (pipelines, pubsub, scripts).

Typical usage:

client, err := redis.New(ctx, cfg, redis.WithOtel())
if err != nil { log.Fatal(err) }

a := app.New()
a.Add(client)   // registers Shutdown + Healthcheck

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

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

Client is a thin wrapper around *redis.Client that adds lifecycle conformance and cheap convenience methods. For anything beyond Get/Set/Del, call Unwrap to get the underlying *redis.Client.

Implements lifecycle.Resource and lifecycle.Healthchecker.

func New added in v1.3.0

func New(ctx context.Context, cfg Config, opts ...Option) (*Client, error)

New connects to Redis and verifies the connection with a Ping. Returns a Client ready for use.

Returns an error if the initial Ping fails — callers should treat this as fatal and not continue startup.

func (*Client) Del

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

Del removes one or more keys. Returns nil even if a key did not exist.

func (*Client) Get

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

Get returns the string value at key, or an error. Wraps redis.Client.Get for the common case.

func (*Client) Healthcheck added in v1.3.0

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

Healthcheck pings the Redis server. Implements lifecycle.Healthchecker.

Cheap (single PING command) and respects ctx deadlines via go-redis's per-command timeout pipeline.

func (*Client) Set

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

Set stores value at key with the given TTL. A ttl of 0 means no expiration.

func (*Client) Shutdown added in v1.3.0

func (c *Client) Shutdown(_ context.Context) error

Shutdown closes the underlying Redis client and releases the connection pool. Implements lifecycle.Resource.

Idempotent and concurrent-safe: the close runs exactly once; every subsequent call returns the same result.

The ctx parameter is currently ignored — go-redis's Close is synchronous and not context-aware. The signature matches lifecycle.Resource for uniform integration with app.App.

func (*Client) Unwrap added in v1.3.0

func (c *Client) Unwrap() *redis.Client

Unwrap returns the underlying *redis.Client. Use for operations not covered by the convenience methods (pipelines, transactions, pubsub, scripts, custom commands).

The returned pointer is owned by Client — do not Close it directly; always go through Shutdown.

type Config

type Config struct {
	// Host is the Redis server hostname or IP. Required.
	Host string

	// Port is the Redis server TCP port. Required.
	Port string

	// Password is the AUTH password. Empty means no AUTH.
	Password string

	// DB is the Redis logical database number (0-15 by default). Default 0.
	DB int
}

Config describes a single Redis instance to connect to. All fields are plain values with no struct tags — consumer apps map their viper keys to fields explicitly inside their own config.NewConfig().

type Option added in v1.3.0

type Option func(*options)

Option configures a new Client.

func WithLogger added in v1.3.0

func WithLogger(l *slog.Logger) Option

WithLogger attaches a *slog.Logger used for lifecycle events. Defaults to slog.Default() when omitted.

func WithOtel added in v1.3.0

func WithOtel() Option

WithOtel enables OpenTelemetry tracing and metrics on every Redis command via go-redis's redisotel extension. Uses the global tracer and meter providers, so otel.Setup must run and be registered with app.App before New so the providers are non-noop.

One span per command is created with the command name, key (if available), and result/error status.

func WithPoolSize added in v1.3.0

func WithPoolSize(n int) Option

WithPoolSize overrides the connection pool size. Default: go-redis uses 10*runtime.NumCPU() if unset.

func WithReadTimeout added in v1.3.0

func WithReadTimeout(d time.Duration) Option

WithReadTimeout overrides the per-command read timeout. Default: go-redis uses 3 seconds if unset.

func WithWriteTimeout added in v1.3.0

func WithWriteTimeout(d time.Duration) Option

WithWriteTimeout overrides the per-command write timeout. Default: go-redis uses ReadTimeout if unset.

Jump to

Keyboard shortcuts

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