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"
|
"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 {
|
if err != nil {
|
||||||
log.Fatal("❌ Konnte nicht zu NATS verbinden: ", err)
|
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 {
|
||||||
|
// 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) {
|
||||||
|
|||||||
@@ -26,11 +26,35 @@ 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()
|
||||||
|
|
||||||
|
// 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 {
|
if err := rdb.Ping(ctx).Err(); err != nil {
|
||||||
return err
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user