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
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 2m25s
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
|
||||
@@ -36,11 +37,60 @@ func main() {
|
||||
}
|
||||
log.Printf("✅ Verbunden mit Redis: %s", redisAddr)
|
||||
|
||||
// 2. NATS VERBINDUNG
|
||||
// 2. NATS VERBINDUNG mit Reconnect-Logik
|
||||
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 {
|
||||
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()
|
||||
|
||||
@@ -48,7 +98,7 @@ func main() {
|
||||
if err != nil {
|
||||
log.Fatal("❌ JSON Encoder Fehler: ", err)
|
||||
}
|
||||
log.Println("✅ Verbunden mit NATS unter", natsURL)
|
||||
log.Printf("✅ Verbunden mit NATS: %s", natsURL)
|
||||
|
||||
// 3. HANDLER: GAME JOIN
|
||||
sub, err := ec.Subscribe("game.join", func(req *game.JoinRequest) {
|
||||
|
||||
@@ -24,13 +24,37 @@ const leaderboardKey = "leaderboard:top"
|
||||
|
||||
func InitLeaderboard(redisAddr string) error {
|
||||
rdb := redis.NewClient(&redis.Options{
|
||||
Addr: redisAddr,
|
||||
DB: 0,
|
||||
Addr: redisAddr,
|
||||
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()
|
||||
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{
|
||||
@@ -38,7 +62,7 @@ func InitLeaderboard(redisAddr string) error {
|
||||
ctx: ctx,
|
||||
}
|
||||
|
||||
log.Println("📊 Redis-Leaderboard verbunden")
|
||||
log.Println("✅ Redis-Leaderboard verbunden")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user