Cache service for the Gas ecosystem. Provides two gas.CacheProvider implementations —
an in-memory backend for development and testing, and a Valkey (Redis-compatible) backend for production.
go get github.com/gasmod/gas-cache| Backend | Package | Use case |
|---|---|---|
| In-memory | github.com/gasmod/gas-cache/memory |
Development, testing, single-instance deployments |
| Valkey (Redis) | github.com/gasmod/gas-cache/valkey |
Production, multi-instance deployments |
Both backends implement gas.Service and gas.CacheProvider. The Valkey backend also
implements gas.HealthReporter and gas.ReadyReporter for Kubernetes-style liveness
and readiness probes.
package main
import (
"github.com/gasmod/gas"
cachemem "github.com/gasmod/gas-cache/memory"
)
func main() {
app := gas.NewApp(
gas.WithSingletonService[*cachemem.Service](cachemem.New()),
// ...
)
app.Run()
}With custom configuration:
cfg := cachemem.DefaultConfig()
cfg.Cache.MaxEntries = 10000
cfg.Cache.DefaultTTL = 5 * time.Minute
cfg.Cache.CleanupInterval = 2 * time.Minute
cachemem.New(cachemem.WithConfig(cfg))package main
import (
"github.com/gasmod/gas"
cachevk "github.com/gasmod/gas-cache/valkey"
)
func main() {
app := gas.NewApp(
gas.WithSingletonService[*cachevk.Service](cachevk.New()),
// ...
)
app.Run()
}With custom configuration:
cfg := cachevk.DefaultConfig()
cfg.Cache.Addr = "valkey.internal:6379"
cfg.Cache.Password = "secret"
cfg.Cache.DB = 1
cfg.Cache.ConnRetries = 3
cachevk.New(cachevk.WithConfig(cfg))Services receive the cache through gas.CacheProvider via constructor injection:
type Service struct {
cache gas.CacheProvider
}
func New(cache gas.CacheProvider) *Service {
return &Service{cache: cache}
}
func (s *Service) Init() error {
ctx := context.Background()
_ = s.cache.Set(ctx, "hello", []byte("world"), 5*time.Minute)
return nil
}For advanced Valkey operations beyond the CacheProvider interface, type-assert to access the underlying client:
type ValkeyProvider interface {
Client() valkey.Client
}
func (s *Service) Init() error {
if vp, ok := s.cache.(ValkeyProvider); ok {
client := vp.Client()
// use client for pub/sub, Lua scripts, etc.
}
return nil
}If WithConfig is not provided, both backends automatically bind configuration from the gas.ConfigProvider injected
via DI. This lets you drive cache settings from environment variables or a config file without any explicit wiring.
| Field | Default | Description |
|---|---|---|
Cache.MaxEntries |
0 |
Max entries (0 = unlimited) |
Cache.CleanupInterval |
1m |
How often expired entries are evicted (0 = disabled) |
Cache.DefaultTTL |
0 |
Default TTL when Set is called with ttl=0 (0 = never expires) |
| Field | Default | Description |
|---|---|---|
Cache.Addr |
localhost:6379 |
Valkey server address (host:port) |
Cache.Password |
Authentication password (empty = no auth) | |
Cache.DB |
0 |
Database number (0-15) |
Cache.DialTimeout |
5s |
Timeout for establishing new connections |
Cache.WriteTimeout |
3s |
Timeout for write operations and periodic PINGs |
Cache.ConnRetries |
0 |
Number of connection retry attempts (0 = no retries) |
Cache.ConnRetryInterval |
2s |
Base retry interval; doubles each attempt (exp. backoff) |
The cachetest package provides a mock implementation of gas.CacheProvider:
import "github.com/gasmod/gas-cache/cachetest"
mock := &cachetest.MockCache{}
mock.GetFn = func(ctx context.Context, key string) ([]byte, error) {
return []byte("hello"), nil
}
// pass mock as gas.CacheProvider
// assert calls:
if mock.CallCount("Get") != 1 {
t.Error("expected one Get call")
}The Valkey backend implements gas.HealthReporter and gas.ReadyReporter:
CheckHealth(ctx)— liveness. Returnscache.ErrClosedonce the service is closed andnilotherwise. The valkey-go client reconnects internally, so a transient network failure is not a liveness failure — a process restart would not help.CheckReady(ctx)— readiness. Issues aPINGagainst the Valkey server using the caller's context. Returns an error while the dependency is unreachable so traffic can be drained until it recovers.
The in-memory backend intentionally does not implement these interfaces: it has no external dependency and no warmup, so liveness and readiness track the service lifecycle that the gas framework already manages.
The root cache package defines two sentinel errors used by both backends:
cache.ErrKeyNotFound // returned by Get when the key does not exist or has expired
cache.ErrClosed // returned when an operation is attempted on a closed service