Private
Public Access
1
0

Enhance Redis and NATS connection logic with retry mechanisms, exponential backoff, and improved error handling.
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 2m25s

This commit is contained in:
Sebastian Unterschütz
2026-01-04 15:44:00 +01:00
parent 43680ece16
commit 932edf74f2
2 changed files with 83 additions and 9 deletions

View File

@@ -7,6 +7,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"sync" "sync"
"time"
"github.com/nats-io/nats.go" "github.com/nats-io/nats.go"
@@ -36,11 +37,60 @@ func main() {
} }
log.Printf("✅ Verbunden mit Redis: %s", redisAddr) log.Printf("✅ Verbunden mit Redis: %s", redisAddr)
// 2. NATS VERBINDUNG // 2. NATS VERBINDUNG mit Reconnect-Logik
natsURL := getEnv("NATS_URL", "nats://localhost:4222") natsURL := getEnv("NATS_URL", "nats://localhost:4222")
nc, err := nats.Connect(natsURL)
nc, err := nats.Connect(
natsURL,
nats.MaxReconnects(-1), // Unbegrenzte Reconnects
nats.ReconnectWait(2*time.Second),
nats.ReconnectBufSize(5*1024*1024), // 5MB Buffer
nats.DisconnectErrHandler(func(nc *nats.Conn, err error) {
if err != nil {
log.Printf("⚠️ NATS getrennt: %v", err)
}
}),
nats.ReconnectHandler(func(nc *nats.Conn) {
log.Printf("✅ NATS wiederverbunden: %s", nc.ConnectedUrl())
}),
nats.ClosedHandler(func(nc *nats.Conn) {
log.Println("❌ NATS Verbindung geschlossen")
}),
nats.Timeout(10*time.Second),
nats.PingInterval(20*time.Second),
nats.MaxPingsOutstanding(5),
)
if err != nil { if err != nil {
log.Fatal("❌ Konnte nicht zu NATS verbinden: ", err) // Retry-Logik für initiales Connect
maxRetries := 10
retryDelay := 2 * time.Second
for i := 0; i < maxRetries; i++ {
log.Printf("⚠️ NATS noch nicht erreichbar (Versuch %d/%d): %v", i+1, maxRetries, err)
log.Printf("⏳ Warte %v vor erneutem Versuch...", retryDelay)
time.Sleep(retryDelay)
nc, err = nats.Connect(
natsURL,
nats.MaxReconnects(-1),
nats.ReconnectWait(2*time.Second),
nats.Timeout(10*time.Second),
)
if err == nil {
break
}
retryDelay = retryDelay * 2 // Exponential backoff
if retryDelay > 30*time.Second {
retryDelay = 30 * time.Second
}
}
if err != nil {
log.Fatalf("❌ Konnte nicht zu NATS verbinden nach %d Versuchen: %v", maxRetries, err)
}
} }
defer nc.Close() defer nc.Close()
@@ -48,7 +98,7 @@ func main() {
if err != nil { if err != nil {
log.Fatal("❌ JSON Encoder Fehler: ", err) log.Fatal("❌ JSON Encoder Fehler: ", err)
} }
log.Println("✅ Verbunden mit NATS unter", natsURL) log.Printf("✅ Verbunden mit NATS: %s", natsURL)
// 3. HANDLER: GAME JOIN // 3. HANDLER: GAME JOIN
sub, err := ec.Subscribe("game.join", func(req *game.JoinRequest) { sub, err := ec.Subscribe("game.join", func(req *game.JoinRequest) {

View File

@@ -24,13 +24,37 @@ const leaderboardKey = "leaderboard:top"
func InitLeaderboard(redisAddr string) error { func InitLeaderboard(redisAddr string) error {
rdb := redis.NewClient(&redis.Options{ rdb := redis.NewClient(&redis.Options{
Addr: redisAddr, Addr: redisAddr,
DB: 0, DB: 0,
MaxRetries: 5,
MinRetryBackoff: 1 * time.Second,
MaxRetryBackoff: 5 * time.Second,
DialTimeout: 10 * time.Second,
ReadTimeout: 3 * time.Second,
WriteTimeout: 3 * time.Second,
}) })
ctx := context.Background() ctx := context.Background()
if err := rdb.Ping(ctx).Err(); err != nil {
return err // Retry-Logik für initiales Connect
maxRetries := 10
retryDelay := 2 * time.Second
for i := 0; i < maxRetries; i++ {
if err := rdb.Ping(ctx).Err(); err != nil {
log.Printf("⚠️ Redis noch nicht erreichbar (Versuch %d/%d): %v", i+1, maxRetries, err)
if i < maxRetries-1 {
log.Printf("⏳ Warte %v vor erneutem Versuch...", retryDelay)
time.Sleep(retryDelay)
retryDelay = retryDelay * 2 // Exponential backoff
if retryDelay > 30*time.Second {
retryDelay = 30 * time.Second
}
continue
}
return fmt.Errorf("Redis nicht erreichbar nach %d Versuchen: %w", maxRetries, err)
}
break // Erfolgreich verbunden
} }
GlobalLeaderboard = &Leaderboard{ GlobalLeaderboard = &Leaderboard{
@@ -38,7 +62,7 @@ func InitLeaderboard(redisAddr string) error {
ctx: ctx, ctx: ctx,
} }
log.Println("📊 Redis-Leaderboard verbunden") log.Println(" Redis-Leaderboard verbunden")
return nil return nil
} }