UpStashinternal/redis/client.go
func NewRedisFromEnv() (*Redis, error) {
_ = godotenv.Load()
if url := os.Getenv("REDIS_URL"); url != "" {
/*
- Converts URL -> redis.Options
- Extracts Addr, Username, Password, TLS Settings
*/
opts, err := goredis.ParseURL(url)
if err != nil {
return nil, fmt.Errorf("parse redis url : %w", err)
}
/*
- Enforces TLS when needed
- Some providers require TLS , but give URLs like redis:// instead of rediss://
If you don’t attach TLSConfig, connection fails.
*/
if opts.TLSConfig == nil && len(url) >= 9 && url[:9] == "redis://" {
opts.TLSConfig = &tls.Config{}
}
// Create Redis Client
rdb := goredis.NewClient(opts)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := rdb.Ping(ctx).Err(); err != nil {
return nil, fmt.Errorf("redis ping (REDIS_URL) : %w", err)
}
return &Redis{
Client: rdb,
}, nil
}
// Fallback to REDIS_ADDR ( LOCAL/DOCKER )
addr := os.Getenv("REDIS_ADDR")
if addr == "" {
return nil, fmt.Errorf("set REDIS_URL (recommended) or REDIS_ADDR")
}
// Create Redis Client ( Non-TLS )
rdb := goredis.NewClient(&goredis.Options{
Addr: addr,
})
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := rdb.Ping(ctx).Err(); err != nil {
return nil, fmt.Errorf("redis ping (REDIS_ADDR) : %w", err)
}
return &Redis{
Client: rdb,
}, nil
}
main.go files to use itEverywhere you currently do:
redisClient,err:=redis.NewRedis(os.Getenv("REDIS_ADDR"))
replace with:
redisClient,err:=redis.NewRedisFromEnv()
Upstash URL in .envUpstash is TLS enabled. Use rediss (TLS):
REDIS_URL=rediss://default:<PASSWORD>@wise-raptor-10797.upstash.io:6379
docker-compose.external.ymlRedis ) remove those services and dependencies , volumes.services:
migrate:
image: migrate/migrate:v4.17.1
env_file:
- .env
volumes:
- ./apps/api-go/migrations:/migrations
command: [
"-path", "/migrations",
"-database", "${DATABASE_URL}",
"up"
]
restart: on-failure
api:
build:
context: .
dockerfile: apps/api-go/Dockerfile
image: runstate-api-go:local
ports:
- "${PORT:-3001}:3001"
env_file:
- .env
depends_on:
migrate:
condition: service_completed_successfully
restart: unless-stopped
monitoring-pusher:
image: runstate-api-go:local
entrypoint: ["/monitoring-pusher"]
env_file:
- .env
depends_on:
migrate:
condition: service_completed_successfully
restart: unless-stopped
worker-monitoring:
image: runstate-api-go:local
entrypoint: ["/worker-monitoring"]
env_file:
- .env
depends_on:
migrate:
condition: service_completed_successfully
restart: unless-stopped
worker-status-change:
image: runstate-api-go:local
entrypoint: ["/worker-status-change"]
env_file:
- .env
depends_on:
migrate:
condition: service_completed_successfully
restart: unless-stopped
worker-notification:
image: runstate-api-go:local
entrypoint: ["/worker-notification"]
env_file:
- .env
depends_on:
migrate:
condition: service_completed_successfully
restart: unless-stopped
docker compose -f docker-compose.external.yml up --build