Skip to content

Commit 44e5619

Browse files
committed
refactor: use retry library
1 parent f9466b5 commit 44e5619

File tree

3 files changed

+61
-90
lines changed

3 files changed

+61
-90
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ require (
5050
github.com/prometheus/client_model v0.6.1 // indirect
5151
github.com/prometheus/common v0.62.0 // indirect
5252
github.com/prometheus/procfs v0.15.1 // indirect
53+
github.com/sethvargo/go-retry v0.3.0 // indirect
5354
github.com/x448/float16 v0.8.4 // indirect
5455
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
5556
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
160160
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
161161
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
162162
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
163+
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
164+
github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
163165
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
164166
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
165167
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=

server/connector.go

Lines changed: 58 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ import (
2121
"github.com/juju/ratelimit"
2222
"github.com/pires/go-proxyproto"
2323
"github.com/sirupsen/logrus"
24+
"github.com/sethvargo/go-retry"
2425
)
2526

2627
const (
2728
handshakeTimeout = 5 * time.Second
2829
backendTimeout = 30 * time.Second
29-
backendRetryInterval = 5 * time.Second
30+
backendRetryInterval = 3 * time.Second
3031
backendStatusTimeout = 1 * time.Second
3132
)
3233

@@ -402,110 +403,77 @@ func (c *Connector) findAndConnectBackend(ctx context.Context, frontendConn net.
402403
WithField("player", playerInfo).
403404
Info("Connecting to backend")
404405

405-
var backendConn net.Conn
406-
var err error
407-
408-
if nextState == mcproto.StateStatus {
409-
// Status request: try to connect once with backendStatusTimeout
410-
backendConn, err = net.DialTimeout("tcp", backendHostPort, backendStatusTimeout)
411-
if err != nil {
406+
// We want to try to connect to the backend every backendRetryInterval
407+
var backendTry retry.Backoff
408+
409+
switch nextState {
410+
case mcproto.StateStatus:
411+
// Status request: try to connect once with backendStatusTimeout
412+
backendTry = retry.NewConstant(backendStatusTimeout)
413+
backendTry = retry.WithMaxRetries(0, backendTry)
414+
case mcproto.StateLogin:
415+
backendTry = retry.NewConstant(backendRetryInterval)
416+
// Connect request: if autoscaler is enabled, try to connect until backendTimeout is reached
417+
if waker != nil {
418+
// Autoscaler enabled: retry until backendTimeout is reached
419+
backendTry = retry.WithMaxDuration(backendTimeout, backendTry)
420+
} else {
421+
// Autoscaler disabled: try to connect once with backendRetryInterval
422+
backendTry = retry.WithMaxRetries(0, backendTry)
423+
}
424+
default:
425+
// Unknown state, do nothing
412426
logrus.
413-
WithError(err).
414427
WithField("client", clientAddr).
415428
WithField("serverAddress", serverAddress).
416-
WithField("backend", backendHostPort).
429+
WithField("nextState", nextState).
417430
WithField("player", playerInfo).
418-
Warn("Unable to connect to backend for status request")
419-
c.metrics.Errors.With("type", "backend_failed").Add(1)
431+
Error("Unknown state, unable to connect to backend")
432+
return
433+
}
420434

421-
if c.connectionNotifier != nil {
422-
notifyErr := c.connectionNotifier.NotifyFailedBackendConnection(ctx, clientAddr, serverAddress, playerInfo, backendHostPort, err)
423-
if notifyErr != nil {
424-
logrus.WithError(notifyErr).Warn("failed to notify failed backend connection")
425-
}
426-
}
435+
var backendConn net.Conn
436+
if retryErr := retry.Do(ctx, backendTry, func(ctx context.Context) error {
437+
logrus.Debug("Attempting to connect")
438+
var err error
439+
backendConn, err = net.Dial("tcp", backendHostPort)
440+
if err != nil { return retry.RetryableError(err) }
441+
return nil
442+
}); retryErr != nil {
443+
logrus.
444+
WithError(retryErr).
445+
WithField("client", clientAddr).
446+
WithField("serverAddress", serverAddress).
447+
WithField("backend", backendHostPort).
448+
WithField("player", playerInfo).
449+
Warn("Unable to connect to backend")
450+
c.metrics.Errors.With("type", "backend_failed").Add(1)
427451

428-
// Return fakeOnline MOTD
429-
if c.fakeOnline && waker != nil {
430-
logrus.Info("Server is offline, sending fakeOnlineMOTD for status request")
431-
writeStatusErr := mcproto.WriteStatusResponse(
432-
frontendConn,
433-
c.fakeOnlineMOTD,
434-
)
435-
if writeStatusErr != nil {
436-
logrus.
437-
WithError(writeStatusErr).
438-
WithField("client", clientAddr).
439-
WithField("serverAddress", serverAddress).
440-
WithField("backend", backendHostPort).
441-
WithField("player", playerInfo).
442-
Error("Failed to write status response")
443-
}
452+
if c.connectionNotifier != nil {
453+
notifyErr := c.connectionNotifier.NotifyFailedBackendConnection(ctx, clientAddr, serverAddress, playerInfo, backendHostPort, retryErr)
454+
if notifyErr != nil {
455+
logrus.WithError(notifyErr).Warn("failed to notify failed backend connection")
444456
}
445-
return
446457
}
447-
} else if nextState == mcproto.StateLogin {
448-
// Connect request
449-
if waker != nil {
450-
logrus.Debug("Connect: Autoscaler is enabled, waiting for backend to be ready")
451-
// Autoscaler enabled: retry until backendTimeout is reached
452-
deadline := time.Now().Add(backendTimeout)
453-
for {
454-
backendConn, err = net.DialTimeout("tcp", backendHostPort, backendRetryInterval)
455-
logrus.Debug("Tries to connect to backend")
456-
457-
if err == nil {
458-
break
459-
}
460-
if time.Now().After(deadline) {
461-
logrus.
462-
WithError(err).
463-
WithField("client", clientAddr).
464-
WithField("serverAddress", serverAddress).
465-
WithField("backend", backendHostPort).
466-
WithField("player", playerInfo).
467-
Warn("Unable to connect to backend after retries (autoscaler enabled)")
468-
c.metrics.Errors.With("type", "backend_failed").Add(1)
469-
if c.connectionNotifier != nil {
470-
notifyErr := c.connectionNotifier.NotifyFailedBackendConnection(ctx, clientAddr, serverAddress, playerInfo, backendHostPort, err)
471-
if notifyErr != nil {
472-
logrus.WithError(notifyErr).Warn("failed to notify failed backend connection")
473-
}
474-
}
475-
return
476-
}
477-
time.Sleep(backendRetryInterval)
478-
}
479-
} else {
480-
logrus.Debug("Connect: Autoscaler is disabled, trying to connect once")
481-
// Autoscaler disabled: try to connect once with backendTimeout
482-
backendConn, err = net.DialTimeout("tcp", backendHostPort, backendTimeout)
483-
if err != nil {
458+
459+
if nextState == mcproto.StateStatus && c.fakeOnline && waker != nil {
460+
logrus.Info("Server is offline, sending fakeOnlineMOTD for status request")
461+
writeStatusErr := mcproto.WriteStatusResponse(
462+
frontendConn,
463+
c.fakeOnlineMOTD,
464+
)
465+
466+
if writeStatusErr != nil {
484467
logrus.
485-
WithError(err).
468+
WithError(writeStatusErr).
486469
WithField("client", clientAddr).
487470
WithField("serverAddress", serverAddress).
488471
WithField("backend", backendHostPort).
489472
WithField("player", playerInfo).
490-
Warn("Unable to connect to backend (autoscaler disabled)")
491-
c.metrics.Errors.With("type", "backend_failed").Add(1)
492-
if c.connectionNotifier != nil {
493-
notifyErr := c.connectionNotifier.NotifyFailedBackendConnection(ctx, clientAddr, serverAddress, playerInfo, backendHostPort, err)
494-
if notifyErr != nil {
495-
logrus.WithError(notifyErr).Warn("failed to notify failed backend connection")
496-
}
497-
}
498-
return
473+
Error("Failed to write status response")
499474
}
500475
}
501-
} else {
502-
// Unknown state, do nothing
503-
logrus.
504-
WithField("client", clientAddr).
505-
WithField("serverAddress", serverAddress).
506-
WithField("nextState", nextState).
507-
WithField("player", playerInfo).
508-
Warn("Unknown state, unable to connect to backend")
476+
509477
return
510478
}
511479

0 commit comments

Comments
 (0)