Documentation
¶
Overview ¶
Package redis holds the process-wide Redis client, the typed cache backend built on it, and the helpers that share its keyspace.
The client is go-redis v9, which speaks to Redis 7 and newer; a deployment on Redis 6 or older needs the v8 client instead.
Index ¶
- Constants
- Variables
- func Cache[T any]() types.Cache[T]
- func Client() (redis.UniversalClient, error)
- func Close() error
- func Del(ctx context.Context, keys ...string) error
- func Expire(ctx context.Context, key string, expiration time.Duration) error
- func Get(ctx context.Context, key string) (cache []byte, err error)
- func GetInt(ctx context.Context, key string) (int64, error)
- func Health(ctx context.Context) error
- func Incr(ctx context.Context, key string) (int64, error)
- func IncrFixedWindow(ctx context.Context, key string, window time.Duration) (int64, error)
- func Init() (err error)
- func Key(key string) string
- func New(cfg config.Redis) (*redis.Client, error)
- func NewCluster(cfg config.Redis) (*redis.ClusterClient, error)
- func RemovePrefix(ctx context.Context, prefix string) (err error)
- func Set(ctx context.Context, key string, data any, expiration ...time.Duration) error
- func SetNX(ctx context.Context, key, value string, expiration time.Duration) (bool, error)
- func SetXX(ctx context.Context, key, value string, expiration time.Duration) (bool, error)
- func TTL(ctx context.Context, key string) (time.Duration, error)
- func ZAdd(ctx context.Context, key string, score float64, members ...string) error
- func ZRange(ctx context.Context, key string, start, stop int64) ([]string, error)
- func ZRangeByScore(ctx context.Context, key, minScore, maxScore string) ([]string, error)
- func ZRem(ctx context.Context, key string, members ...string) error
- func ZRemRangeByScore(ctx context.Context, key, minScore, maxScore string) error
Constants ¶
const ( // TTLKeyNotExists is reported for a key that does not exist. TTLKeyNotExists = time.Duration(-2) // TTLNoExpiry is reported for a key that exists without a ttl. TTLNoExpiry = time.Duration(-1) )
The two values Redis answers TTL with when there is no deadline to report. Both are negative, so a caller that compares the result against a positive duration has to test for them before reading it as a remaining lifetime.
They are status codes rather than lengths of time: the client hands the reply integer back as a Duration without scaling it by the reply's unit, so -2 arrives as -2 nanoseconds. Spelling them in seconds would build constants no reply can ever equal, and every comparison against them would silently report "not this case".
Variables ¶
var ( ErrKeyNotExists = errors.New("key no longer exists, may be expired") ErrRedisIsDisabled = errors.New("redis is disabled") )
Functions ¶
func Cache ¶
Cache returns a Redis-backed typed cache handle wrapped with tracing. The handle is stateless: the context of each call flows to the Redis client.
Unlike the in-memory backends, which keep one isolated store per value type, every redis.Cache shares the application's Redis keyspace: the caller-supplied key plus the configured namespace is the storage key. Callers own key isolation and build keys through a per-domain key builder (such as the iam session key builders). Invalidation paths using the raw redis helpers rely on those same builders, which is why the framework must not rewrite keys behind the caller's back.
Errors are returned to the caller without logging here; the service and controller layers own error reporting. The one exception is an entry whose bytes do not decode as T: Get drops it, logs the key at Warn and answers ErrEntryNotFound, so a stale or foreign encoding reads as a miss instead of a failure.
func Client ¶
func Client() (redis.UniversalClient, error)
Client returns the initialized Redis client handle, standalone or cluster depending on configuration.
It reports ErrRedisIsDisabled whenever no handle is held, which covers a deployment that never enabled Redis, one whose Init failed, and a process past Close. Every operation in this package goes through it, so an absent handle is an error at the call site instead of a zero value the caller cannot tell from a real answer.
func Close ¶
func Close() error
Close releases the connection and drops the handle, so operations that arrive afterwards report ErrRedisIsDisabled instead of reaching a closed connection. A process that never connected reports no error.
func Del ¶
Del removes the given keys. Keys that do not exist are not an error: the server reports how many it removed, which this drops.
func GetInt ¶
GetInt reads the value at key and decodes it as an integer, reporting ErrKeyNotExists when the key does not exist.
func Health ¶
Health reports whether the held connection still answers, which is what a readiness probe asks. A process holding no handle reports ErrRedisIsDisabled, the same answer every operation gives it.
A nil ctx is treated as context.Background. The round trip is bounded by pingTimeout regardless, so a caller whose own deadline is further out does not wait on a connection that is gone.
func Incr ¶
Incr increments the integer at key by one and returns the new value, creating the key at zero first when it does not exist.
The read and the write are one Redis operation, which is what makes it usable as a counter under concurrency: a caller that instead read, added, and wrote back would lose increments to every interleaving of two requests.
func IncrFixedWindow ¶
IncrFixedWindow increments the integer at key by one and returns the new value, bounding the count to a window that opens with its first increment.
The window is set only while the key has no ttl — on the increment that creates the key, or on one that finds a count left without a ttl — and later increments never extend it, so the count always resets a fixed time after it began. Extending the window on every increment would let anyone who keeps incrementing hold the count up indefinitely, and a count without a ttl would never reset at all.
The increment and the ttl travel as one MULTI/EXEC transaction on a single key. No process can stop between the two and leave a count that never expires, and because the transaction names one key it stays on one slot in cluster mode; widening it to more keys would break that.
window must be a positive whole number of milliseconds, the precision Redis keeps ttls in; any other value is rejected rather than rounded.
func Init ¶
func Init() (err error)
Init connects the process-wide client and verifies it with a ping, then instruments it for tracing when tracing is configured on. A deployment that leaves Redis disabled keeps no handle, which every operation reports through Client. A second call on a connected process does nothing.
func Key ¶
Key returns the storage key for key: the configured namespace, the separator, then the key itself. A key already carrying the namespace is returned unchanged, so applying it twice is harmless.
Every operation in this package applies it. A caller reaching past them — working through the Client handle for a data structure this package does not wrap — has to apply it too, or its keys land outside the namespace everything else shares.
func New ¶
New builds a standalone client from cfg without installing it as the process-wide handle. Init builds its handle with it, and a caller needing a connection of its own — one pointed at another database, say — can too.
func NewCluster ¶
func NewCluster(cfg config.Redis) (*redis.ClusterClient, error)
NewCluster is New for a cluster deployment, reading cfg.Addrs instead of the single address.
func RemovePrefix ¶
RemovePrefix scans for and deletes every key matching prefix, for example myprefix*. A prefix without a trailing wildcard gets one, and the namespace applies as it does to every other key.
func Set ¶
Set stores data at key. The key expires after config.App.Redis.Expiration unless an expiration is given. A custom type or struct must implement encoding.BinaryMarshaler.
func SetXX ¶
SetXX sets key to value with expiration only when the key already exists, and reports whether it did.
It is the write for a key that must not come back once removed. Checking for the key and then setting it are two commands a delete can fall between, and the set would then recreate what was just removed; here the check and the write are one Redis command.
func TTL ¶
TTL reports the remaining ttl of a key.
Redis answers the two "nothing to report" cases with negative durations instead of an error, and they are passed through unchanged: TTLKeyNotExists for a key that is not there, TTLNoExpiry for a key that is there and never expires. A caller comparing the result against a deadline has to rule both out first, because either one compares as less than any positive duration.
func ZRangeByScore ¶
ZRangeByScore returns sorted set members whose scores are between minScore and maxScore.
Types ¶
This section is empty.