Files
gochat/internal/app/redis.go
T

67 lines
1.7 KiB
Go

package app
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"github.com/gochat/gochat/internal/config"
"github.com/gochat/gochat/pkg/logger"
"github.com/redis/go-redis/v9"
)
// NewRedisClient creates a Redis client for caching, Pub/Sub, and sessions.
// Reference: Chatwoot config/cable.yml Redis adapter configuration
func NewRedisClient(cfg *config.RedisConfig) (*redis.Client, error) {
opts, err := parseRedisURL(cfg.URL)
if err != nil {
return nil, fmt.Errorf("failed to parse Redis URL: %w", err)
}
if cfg.Password != "" {
opts.Password = cfg.Password
}
poolSize := cfg.PoolSize
if poolSize <= 0 {
poolSize = 50
}
opts.PoolSize = poolSize
client := redis.NewClient(opts)
// Verify connection
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := client.Ping(ctx).Err(); err != nil {
return nil, fmt.Errorf("failed to connect to Redis: %w", err)
}
logger.L().Infof("Connected to Redis: %s (pool=%d)", cfg.URL, poolSize)
return client, nil
}
// parseRedisURL parses a Redis URL into redis.Options.
// Handles both "redis://host:port" and "redis://user:password@host:port/db" formats.
func parseRedisURL(urlStr string) (*redis.Options, error) {
opts, err := redis.ParseURL(urlStr)
if err != nil {
// Fallback: simple host:port parsing
parts := strings.Split(strings.TrimPrefix(urlStr, "redis://"), ":")
if len(parts) < 2 {
return nil, fmt.Errorf("invalid Redis URL format: %s", urlStr)
}
port, err := strconv.Atoi(parts[1])
if err != nil {
return nil, fmt.Errorf("invalid Redis port: %s", parts[1])
}
opts = &redis.Options{
Addr: fmt.Sprintf("%s:%d", parts[0], port),
}
}
return opts, nil
}