veza/veza-backend-api/internal/testutils/setup_redis.go
2025-12-16 11:23:49 -05:00

78 lines
1.8 KiB
Go

package testutils
import (
"context"
"sync"
"github.com/redis/go-redis/v9"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
"go.uber.org/zap"
)
var (
redisContainer testcontainers.Container
redisClient *redis.Client
redisOnce sync.Once
redisErr error
)
// GetTestRedisClient ensures the Redis container is running and returns a client.
// It uses a singleton pattern to start the container only once per test run.
func GetTestRedisClient(ctx context.Context) (*redis.Client, error) {
redisOnce.Do(func() {
redisErr = setupRedisContainer(ctx)
})
return redisClient, redisErr
}
func setupRedisContainer(ctx context.Context) error {
logger := zap.NewNop()
if zap.L() != nil {
logger = zap.L()
}
logger.Info("Starting Redis testcontainer")
req := testcontainers.ContainerRequest{
Image: "redis:7-alpine",
ExposedPorts: []string{"6379/tcp"},
WaitingFor: wait.ForLog("Ready to accept connections"),
}
var containerErr error
redisContainer, containerErr = testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
})
if containerErr != nil {
logger.Error("Failed to start Redis testcontainer", zap.Error(containerErr))
return containerErr
}
endpoint, err := redisContainer.Endpoint(ctx, "")
if err != nil {
return err
}
redisClient = redis.NewClient(&redis.Options{
Addr: endpoint,
})
// Wait for Redis to be ready
if err := redisClient.Ping(ctx).Err(); err != nil {
return err
}
logger.Info("Redis testcontainer started successfully")
return nil
}
// TerminateRedisContainer allows manual termination if needed (mostly for cleanup)
func TerminateRedisContainer(ctx context.Context) error {
if redisContainer != nil {
return redisContainer.Terminate(ctx)
}
return nil
}