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 }