Documentation
¶
Overview ¶
Package cachex provides the unified cache API for Aisphere Kernel.
cachex is the ONLY cache abstraction that business code should depend on. It exposes a stable Cache interface backed by Redis (single-node or cluster), with JSON serialization, context propagation, and error normalization built in.
Quickstart ¶
import (
"github.com/aisphereio/kernel/cachex"
_ "github.com/aisphereio/kernel/cachex/redis" // register "redis" driver
)
cache, err := cachex.New(cachex.Config{
Driver: "redis",
Addrs: []string{"localhost:6379"},
})
if err != nil { return err }
defer cache.Close()
// Set with TTL
err = cache.Set(ctx, "user:123", user, 5*time.Minute)
// Get (auto-deserializes JSON into dest)
var user User
err = cache.Get(ctx, "user:123", &user)
// GetOrSet: cache-through pattern (prevents cache penetration)
err = cache.GetOrSet(ctx, "user:123", &user, 5*time.Minute, func(ctx context.Context) (*User, error) {
return db.FindUser(ctx, 123)
})
// SetIfNotExist: distributed lock primitive
ok, err := cache.SetIfNotExist(ctx, "lock:job:42", "owner", 30*time.Second)
// Incr: atomic counter
count, err := cache.Incr(ctx, "rate_limit:user:123")
Drivers ¶
import _ "github.com/aisphereio/kernel/cachex/redis" // registers "redis"
The redis driver uses github.com/redis/go-redis/v9 and supports both single-node and cluster modes (set Config.Cluster = true).
Forbidden patterns ¶
Do not import `github.com/redis/go-redis/v9` in business code. Use the cachex.Cache interface. Do not use `encoding/json` directly for cache serialization — cachex handles it internally.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotFound is returned by Get when the key does not exist. // It is the cache equivalent of dbx.ErrNoRows. ErrNotFound = errors.New("cachex: key not found") // ErrNilConfig is returned by New when Config is missing required fields. ErrNilConfig = errors.New("cachex: config is missing required fields") // ErrUnknownDriver is returned when the driver name has not been registered. ErrUnknownDriver = errors.New("cachex: unknown driver (did you import cachex/redis?)") // ErrClosed is returned when a closed cache is used. ErrClosed = errors.New("cachex: cache is closed") // ErrTypeMismatch is returned when Get cannot deserialize into the target type. ErrTypeMismatch = errors.New("cachex: type mismatch during deserialization") // ErrNilValue is returned when attempting to cache a nil value via GetOrSet. ErrNilValue = errors.New("cachex: value function returned nil") )
Public sentinel errors.
Functions ¶
func IsDriverRegistered ¶
IsDriverRegistered returns true if the named driver has been registered.
func RegisterDriver ¶
func RegisterDriver(name string, fn DriverOpener)
RegisterDriver registers a driver opener under the given name. Called by cachex/redis in its init() function.
func RegisteredDrivers ¶
func RegisteredDrivers() []string
RegisteredDrivers returns the names of all registered drivers.
Types ¶
type Cache ¶
type Cache interface {
// Get retrieves the value for key and deserializes into dest.
// Returns ErrNotFound if the key does not exist.
Get(ctx context.Context, key string, dest any) error
// Set stores value at key with the given TTL.
// TTL == 0 means no expiration.
Set(ctx context.Context, key string, value any, ttl time.Duration) error
// Del removes one or more keys.
Del(ctx context.Context, keys ...string) error
// Exists checks if any of the keys exist. Returns count.
Exists(ctx context.Context, keys ...string) (int64, error)
// Expire sets a TTL on an existing key. No-op if key doesn't exist.
Expire(ctx context.Context, key string, ttl time.Duration) error
// TTL returns the remaining TTL of a key.
// Returns -1 if key has no expiration.
// Returns -2 if key does not exist.
TTL(ctx context.Context, key string) (time.Duration, error)
// MGet retrieves multiple keys. dest must be *[]T or *[]any.
// Missing keys appear as nil in the result.
MGet(ctx context.Context, keys []string, dest any) error
// MSet sets multiple key-value pairs with the same TTL.
MSet(ctx context.Context, pairs map[string]any, ttl time.Duration) error
// GetOrSet retrieves the value for key. If the key is missing, it calls
// fn to compute the value, caches it with the given TTL, and returns it.
// This is the standard cache penetration prevention pattern.
GetOrSet(ctx context.Context, key string, dest any, ttl time.Duration, fn func(ctx context.Context) (any, error)) error
// SetIfNotExist sets key=value with TTL only if key does not exist.
// Returns true if the key was set (i.e., acquired).
SetIfNotExist(ctx context.Context, key string, value any, ttl time.Duration) (bool, error)
// Incr atomically increments key by 1. Creates the key with value 1 if
// it doesn't exist. Returns the new value.
Incr(ctx context.Context, key string) (int64, error)
// IncrBy atomically increments key by delta. Returns the new value.
IncrBy(ctx context.Context, key string, delta int64) (int64, error)
// Decr atomically decrements key by 1. Returns the new value.
Decr(ctx context.Context, key string) (int64, error)
// Publish sends a message to a channel. Returns the number of subscribers.
Publish(ctx context.Context, channel string, message any) (int64, error)
// Subscribe subscribes to channels and returns a Subscription.
// Call Subscription.Close() to stop receiving.
Subscribe(ctx context.Context, channels ...string) (*Subscription, error)
// HSet sets a field in a hash.
HSet(ctx context.Context, key, field string, value any) error
// HGet gets a field from a hash and deserializes into dest.
// Returns ErrNotFound if the field does not exist.
HGet(ctx context.Context, key, field string, dest any) error
// HGetAll returns all fields of a hash as a map.
// dest must be *map[string]any or *map[string]T.
HGetAll(ctx context.Context, key string, dest any) error
// HDel removes fields from a hash.
HDel(ctx context.Context, key string, fields ...string) error
// LPush prepends values to a list.
LPush(ctx context.Context, key string, values ...any) error
// RPush appends values to a list.
RPush(ctx context.Context, key string, values ...any) error
// LPop removes and returns the first element.
LPop(ctx context.Context, key string, dest any) error
// RPop removes and returns the last element.
RPop(ctx context.Context, key string, dest any) error
// LRange returns a range of elements from a list.
// dest must be *[]T or *[]any.
LRange(ctx context.Context, key string, start, stop int64, dest any) error
// LLen returns the length of a list.
LLen(ctx context.Context, key string) (int64, error)
// SAdd adds members to a set.
SAdd(ctx context.Context, key string, members ...any) error
// SRem removes members from a set.
SRem(ctx context.Context, key string, members ...any) error
// SMembers returns all members of a set.
// dest must be *[]T or *[]any.
SMembers(ctx context.Context, key string, dest any) error
// SIsMember checks if a value is in a set.
SIsMember(ctx context.Context, key string, member any) (bool, error)
// Ping verifies the cache is reachable.
Ping(ctx context.Context) error
// Close closes the cache connection. Idempotent.
Close() error
// DriverName returns the registered driver name.
DriverName() string
}
Cache is the runtime cache interface used by kernel modules and apps.
All methods accept context.Context. Methods that take a dest pointer (Get / GetOrSet) auto-serialize/deserialize via JSON.
type Config ¶
type Config struct {
// Driver selects the registered driver: "redis".
Driver string `json:"driver"`
// Addrs is the list of Redis node addresses.
// Single-node: ["localhost:6379"]
// Cluster: ["node1:6379", "node2:6379", "node3:6379"]
Addrs []string `json:"addrs"`
// Username for AUTH (Redis 6+ ACL).
Username string `json:"username"`
// Password for AUTH.
Password string `json:"password"`
// DB selects the Redis database (0-15 for single-node; ignored in cluster).
DB int `json:"db"`
// MasterName enables Sentinel mode (non-empty = sentinel).
MasterName string `json:"master_name"`
// Cluster enables cluster mode. If true, Addrs are seed nodes.
Cluster bool `json:"cluster"`
// PoolSize is the max number of socket connections.
// Default is 10 * runtime.GOMAXPROCS.
PoolSize int `json:"pool_size"`
// MinIdleConns is the minimum number of idle connections.
MinIdleConns int `json:"min_idle_conns"`
// DialTimeout is the timeout for establishing connections.
DialTimeout time.Duration `json:"dial_timeout_ns"`
// ReadTimeout is the timeout for socket reads.
ReadTimeout time.Duration `json:"read_timeout_ns"`
// WriteTimeout is the timeout for socket writes.
WriteTimeout time.Duration `json:"write_timeout_ns"`
// KeyPrefix is prepended to all keys (namespace isolation).
KeyPrefix string `json:"key_prefix"`
// TLSEnabled enables TLS.
TLSEnabled bool `json:"tls_enabled"`
// TLSSkipVerify skips TLS certificate verification.
TLSSkipVerify bool `json:"tls_skip_verify"`
}
Config holds the configuration for a cache connection.
type DriverOpener ¶
DriverOpener opens a Cache for the given Config.
type Message ¶
type Message struct {
Channel string
Pattern string // non-empty if subscribed via pattern
Payload string
}
Message is a single Pub/Sub message.
type Subscription ¶
type Subscription struct {
// Channel receives messages from all subscribed channels.
Channel <-chan *Message
// internal fields (set by driver implementation)
UnsubscribeFn func(channels ...string) error
CloseFn func() error
}
Subscription represents an active Pub/Sub subscription.
func (*Subscription) Close ¶
func (s *Subscription) Close() error
Close closes the subscription entirely.
func (*Subscription) Unsubscribe ¶
func (s *Subscription) Unsubscribe(channels ...string) error
Unsubscribe stops receiving from the given channels.