1
0
Fork 0
cmpt815perf/lib/redis.go

92 lines
2.7 KiB
Go
Raw Permalink Normal View History

2024-12-04 19:09:32 -06:00
package lib
import (
"context"
"encoding/json"
"fmt"
"log"
"time"
"github.com/redis/go-redis/v9"
)
// RedisStorage implements a Redis-backed caching layer for test data.
// It provides fast access to frequently requested data while reducing database load.
type RedisStorage struct {
client *redis.Client
}
// NewRedisStorage creates and initializes a new Redis connection with the provided URL.
// It verifies the connection and configures default timeouts.
func NewRedisStorage(url string) (*RedisStorage, error) {
opt, err := redis.ParseURL(url)
if err != nil {
return nil, fmt.Errorf("failed to parse Redis URL: %v", err)
}
client := redis.NewClient(opt)
// Verify connection is working
ctx := context.Background()
if err := client.Ping(ctx).Err(); err != nil {
return nil, fmt.Errorf("failed to connect to Redis: %v", err)
}
log.Printf("Successfully connected to Redis")
return &RedisStorage{client: client}, nil
}
// GetTestData retrieves cached test data if available.
// Returns (nil, redis.Nil) if key doesn't exist.
func (s *RedisStorage) GetTestData(ctx context.Context) (*TestData, error) {
data, err := s.client.Get(ctx, "test_data").Bytes()
if err != nil {
if err == redis.Nil {
log.Printf("Redis: Cache miss - key not found")
} else {
log.Printf("Redis: Error retrieving data: %v", err)
}
return nil, err
}
var testData TestData
if err := json.Unmarshal(data, &testData); err != nil {
log.Printf("Redis: Error deserializing cached data: %v", err)
return nil, err
}
log.Printf("Redis: Cache hit - retrieved data: %+v", testData)
return &testData, nil
}
// SaveTestData caches the provided test data with a 1-hour TTL.
// Existing data for the same key will be overwritten.
func (s *RedisStorage) SaveTestData(ctx context.Context, data *TestData) error {
jsonData, err := json.Marshal(data)
if err != nil {
log.Printf("Redis: Error serializing data: %v", err)
return err
}
err = s.client.Set(ctx, "test_data", jsonData, 1*time.Hour).Err()
if err != nil {
log.Printf("Redis: Error writing to cache: %v", err)
return err
}
log.Printf("Redis: Successfully cached data: %+v", data)
return nil
}
// InvalidateTestData removes the test data from cache.
// This is typically called when the underlying data is updated.
func (s *RedisStorage) InvalidateTestData(ctx context.Context) error {
err := s.client.Del(ctx, "test_data").Err()
if err != nil {
log.Printf("Redis: Error invalidating cache: %v", err)
} else {
log.Printf("Redis: Successfully invalidated cached data")
}
return err
}