Files
valkey/valkey.go

93 lines
2.4 KiB
Go
Raw Permalink Normal View History

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 }