
Reviewed-on: #1 Co-authored-by: Ron Rise <ron@siteworxpro.com> Co-committed-by: Ron Rise <ron@siteworxpro.com>
120 lines
2.5 KiB
Go
120 lines
2.5 KiB
Go
package redis
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
type contextKey string
|
|
|
|
const redisKey contextKey = "redisClient"
|
|
|
|
const CacheKey = "top-wallpaper:latestImage"
|
|
|
|
type Cache interface {
|
|
Get(key string) (string, error)
|
|
Set(key string, value string, expiration int64) error
|
|
Close() error
|
|
}
|
|
|
|
type Redis struct {
|
|
client *redis.Client
|
|
}
|
|
|
|
func NewRedis() (*Redis, error) {
|
|
|
|
redisUrl := os.Getenv("REDIS_URL")
|
|
if redisUrl == "" {
|
|
return nil, errors.New("REDIS_URL not set, cannot initialize Redis client")
|
|
}
|
|
|
|
redisPort := os.Getenv("REDIS_PORT")
|
|
if redisPort == "" {
|
|
redisPort = "6379"
|
|
}
|
|
|
|
redisDb := os.Getenv("REDIS_DB")
|
|
if redisDb == "" {
|
|
redisDb = "0"
|
|
}
|
|
|
|
redisDbInt, err := strconv.ParseInt(redisDb, 10, 64)
|
|
if err != nil {
|
|
return nil, errors.New("REDIS_DB is not a valid integer, cannot initialize Redis client")
|
|
}
|
|
|
|
rc := redis.NewClient(&redis.Options{
|
|
Addr: fmt.Sprintf("%s:%s", redisUrl, redisPort),
|
|
Password: os.Getenv("REDIS_PASSWORD"),
|
|
DB: int(redisDbInt),
|
|
})
|
|
|
|
cmd := rc.Ping(context.Background())
|
|
|
|
if cmd.Err() != nil {
|
|
return nil, fmt.Errorf("could not connect to Redis: %v", cmd.Err())
|
|
}
|
|
if cmd.Val() != "PONG" {
|
|
return nil, fmt.Errorf("unexpected response from Redis: %s", cmd.Val())
|
|
}
|
|
|
|
return &Redis{
|
|
client: rc,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Redis) Get(key string) (string, error) {
|
|
cmd := r.client.Get(context.Background(), key)
|
|
if cmd.Err() != nil {
|
|
if errors.Is(cmd.Err(), redis.Nil) {
|
|
return "", nil // Key does not exist
|
|
}
|
|
return "", fmt.Errorf("could not get value for key %s: %v", key, cmd.Err())
|
|
}
|
|
return cmd.Val(), nil
|
|
}
|
|
|
|
func (r *Redis) Set(key string, value string, expiration time.Duration) error {
|
|
cmd := r.client.Set(context.Background(), key, value, expiration)
|
|
if cmd.Err() != nil {
|
|
return fmt.Errorf("could not set value for key %s: %v", key, cmd.Err())
|
|
}
|
|
if cmd.Val() != "OK" {
|
|
return fmt.Errorf("unexpected response from Redis when setting key %s: %s", key, cmd.Val())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *Redis) Close() error {
|
|
if r.client == nil {
|
|
return nil
|
|
}
|
|
err := r.client.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("could not close Redis client: %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func WithContext(ctx context.Context, r *Redis) context.Context {
|
|
return context.WithValue(ctx, redisKey, r)
|
|
}
|
|
|
|
func FromContext(ctx context.Context) (*Redis, error) {
|
|
r, ok := ctx.Value(redisKey).(*Redis)
|
|
if !ok {
|
|
return nil, errors.New("no Redis client found in context")
|
|
}
|
|
if r == nil {
|
|
return nil, errors.New("redis client is nil")
|
|
}
|
|
return r, nil
|
|
}
|