package service import ( "context" "os" "time" "github.com/go-redis/redis/v8" ) var ctx = context.Background() type RedisService struct { Client *redis.Client } // NewRedisService creates and returns a new RedisService func NewRedisService() (*RedisService, error) { redisAddr := os.Getenv("REDIS_ADDR") if redisAddr == "" { redisAddr = "localhost:6389" // Fallback for local dev without Docker } rdb := redis.NewClient(&redis.Options{ Addr: redisAddr, }) // Ping the server to check the connection if _, err := rdb.Ping(ctx).Result(); err != nil { return nil, err } // [DEV-FIX] Disable stop-writes-on-bgsave-error to allow writes even if persistence fails // This is common in dev docker environments with permission issues. rdb.ConfigSet(ctx, "stop-writes-on-bgsave-error", "no") return &RedisService{Client: rdb}, nil } func (s *RedisService) Ping(ctx context.Context) error { if s.Client == nil { return os.ErrInvalid } return s.Client.Ping(ctx).Err() } // StoreVerificationCode saves the SMS verification code with a 3-minute expiration func (s *RedisService) StoreVerificationCode(phone, code string) error { // Key format: "sms_verify:01012345678" key := "sms_verify:" + phone expiration := 3 * time.Minute err := s.Client.Set(ctx, key, code, expiration).Err() return err } // GetVerificationCode retrieves the SMS verification code func (s *RedisService) GetVerificationCode(phone string) (string, error) { key := "sms_verify:" + phone code, err := s.Client.Get(ctx, key).Result() if err == redis.Nil { // Key does not exist (expired or incorrect phone number) return "", nil } else if err != nil { return "", err } return code, nil } // DeleteVerificationCode removes the verification code after successful verification func (s *RedisService) DeleteVerificationCode(phone string) error { key := "sms_verify:" + phone return s.Client.Del(ctx, key).Err() } // Set stores a key-value pair with expiration func (s *RedisService) Set(key string, value string, expiration time.Duration) error { return s.Client.Set(ctx, key, value, expiration).Err() } // Get retrieves a value by key func (s *RedisService) Get(key string) (string, error) { val, err := s.Client.Get(ctx, key).Result() if err == redis.Nil { return "", nil } return val, err } // Delete removes a key func (s *RedisService) Delete(key string) error { return s.Client.Del(ctx, key).Err() }