feat(valkey): initial stable release v0.9.0
Valkey (Redis-compatible) client component with launcher lifecycle and health check integration. What's included: - Config with Addrs, Password, SelectDB, CacheSizeEachConn (env-driven) - Provider interface exposing native valkey-go Client() directly (no wrapper) - Component interface: launcher.Component + health.Checkable + Provider - New(logger, cfg) constructor for lifecycle registration via lc.Append - Health check via PING at LevelDegraded priority - Graceful shutdown calling client.Close() in OnStop Tested-via: todo-api POC integration Reviewed-against: docs/adr/
This commit is contained in:
92
valkey.go
Normal file
92
valkey.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package valkey
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
vk "github.com/valkey-io/valkey-go"
|
||||
|
||||
"code.nochebuena.dev/go/health"
|
||||
"code.nochebuena.dev/go/launcher"
|
||||
"code.nochebuena.dev/go/logz"
|
||||
)
|
||||
|
||||
// Provider is the minimal interface for consumers that only need the valkey client.
|
||||
type Provider interface {
|
||||
Client() vk.Client
|
||||
}
|
||||
|
||||
// Component adds lifecycle management and health check to Provider.
|
||||
type Component interface {
|
||||
launcher.Component
|
||||
health.Checkable
|
||||
Provider
|
||||
}
|
||||
|
||||
// Config holds Valkey connection settings.
|
||||
type Config struct {
|
||||
Addrs []string `env:"VK_ADDRS,required" envSeparator:","`
|
||||
Password string `env:"VK_PASSWORD"`
|
||||
SelectDB int `env:"VK_DB" envDefault:"0"`
|
||||
CacheSizeEachConn int `env:"VK_CLIENT_CACHE_MB" envDefault:"0"` // MB; 0 = disable
|
||||
}
|
||||
|
||||
type vkComponent struct {
|
||||
cfg Config
|
||||
logger logz.Logger
|
||||
client vk.Client
|
||||
}
|
||||
|
||||
// New returns a valkey Component. Call lc.Append(vk) to manage its lifecycle.
|
||||
func New(logger logz.Logger, cfg Config) Component {
|
||||
return &vkComponent{cfg: cfg, logger: logger}
|
||||
}
|
||||
|
||||
func (v *vkComponent) OnInit() error {
|
||||
opts := vk.ClientOption{
|
||||
InitAddress: v.cfg.Addrs,
|
||||
Password: v.cfg.Password,
|
||||
SelectDB: v.cfg.SelectDB,
|
||||
}
|
||||
if v.cfg.CacheSizeEachConn > 0 {
|
||||
opts.CacheSizeEachConn = v.cfg.CacheSizeEachConn * 1024 * 1024
|
||||
}
|
||||
client, err := vk.NewClient(opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("valkey: failed to create client: %w", err)
|
||||
}
|
||||
v.client = client
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *vkComponent) OnStart() error {
|
||||
v.logger.Info("valkey: verifying connection")
|
||||
if v.client == nil {
|
||||
return fmt.Errorf("valkey: client not initialized")
|
||||
}
|
||||
if err := v.client.Do(context.Background(), v.client.B().Ping().Build()).Error(); err != nil {
|
||||
return fmt.Errorf("valkey: ping failed: %w", err)
|
||||
}
|
||||
v.logger.Info("valkey: connected")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *vkComponent) OnStop() error {
|
||||
v.logger.Info("valkey: closing client")
|
||||
if v.client != nil {
|
||||
v.client.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *vkComponent) Client() vk.Client { return v.client }
|
||||
|
||||
func (v *vkComponent) HealthCheck(ctx context.Context) error {
|
||||
if v.client == nil {
|
||||
return fmt.Errorf("valkey: client not initialized")
|
||||
}
|
||||
return v.client.Do(ctx, v.client.B().Ping().Build()).Error()
|
||||
}
|
||||
|
||||
func (v *vkComponent) Name() string { return "valkey" }
|
||||
func (v *vkComponent) Priority() health.Level { return health.LevelDegraded }
|
||||
Reference in New Issue
Block a user