Skip to content

Commit 6905f03

Browse files
authored
fix: rcon reconnection data racing issue (#28)
* fix: rcon reconnection data racing issue * fix: reconnection nil issue
1 parent 31972aa commit 6905f03

File tree

3 files changed

+42
-12
lines changed

3 files changed

+42
-12
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ temp/
6969
# Local pgSQL db
7070
.postgres/
7171

72+
# Local Factorio
73+
.factorio/
74+
factorio/
75+
7276
# Debug
7377
__debug*
7478

cspell.config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@ words:
88
- Ayaka
99
- cenkalti
1010
- Factorio
11+
- factorioapi
1112
- fatcontext
1213
- gorcon
1314
- grpcotel
1415
- grpcpkg
16+
- grpcservers
17+
- grpcservices
1518
- healthz
1619
- httppkg
1720
- labstack
21+
- maxbrunsfeld
1822
- Neko
1923
- nekomeowww
2024
- nolint

internal/rcon/rcon.go

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/nekomeowww/factorio-rcon-api/v2/internal/configs"
1717
"github.com/nekomeowww/fo"
1818
"github.com/nekomeowww/xo/logger"
19+
"github.com/samber/lo"
1920
"go.uber.org/fx"
2021
"go.uber.org/zap"
2122
)
@@ -105,6 +106,7 @@ func NewRCON() func(NewRCONParams) (RCON, error) {
105106
if connWrapper.Conn != nil {
106107
return connWrapper.Conn.Close()
107108
}
109+
108110
return nil
109111
})
110112
},
@@ -124,17 +126,38 @@ func (r *RCONConn) connectionManager() {
124126
case <-r.reconnectChan:
125127
r.ready.Store(false)
126128

127-
err := fo.Invoke0(r.ctx, func() error {
128-
return backoff.Retry(func() error {
129-
return r.establishConnection(r.ctx)
129+
r.mutex.Lock()
130+
r.Conn = nil
131+
r.mutex.Unlock()
132+
133+
conn, err := fo.Invoke(r.ctx, func() (*rcon.Conn, error) {
134+
var err error
135+
var rconConn *rcon.Conn
136+
137+
err = backoff.Retry(func() error {
138+
rconConn, err = r.establishConnection(r.ctx)
139+
if err != nil {
140+
return err
141+
}
142+
143+
return nil
130144
}, backoffStrategy)
145+
if err != nil {
146+
return nil, err
147+
}
148+
149+
return rconConn, err
131150
})
132151

133152
if err != nil {
134153
r.logger.Error("failed to establish RCON connection after retries", zap.Error(err))
135154
continue
136155
}
137156

157+
r.mutex.Lock()
158+
r.Conn = conn
159+
r.mutex.Unlock()
160+
138161
r.ready.Store(true)
139162

140163
select {
@@ -145,8 +168,8 @@ func (r *RCONConn) connectionManager() {
145168
}
146169
}
147170

148-
func (r *RCONConn) establishConnection(ctx context.Context) error {
149-
return fo.Invoke0(ctx, func() error {
171+
func (r *RCONConn) establishConnection(ctx context.Context) (*rcon.Conn, error) {
172+
return fo.Invoke(ctx, func() (*rcon.Conn, error) {
150173
r.mutex.Lock()
151174
defer r.mutex.Unlock()
152175

@@ -157,21 +180,19 @@ func (r *RCONConn) establishConnection(ctx context.Context) error {
157180
conn, err := rcon.Dial(net.JoinHostPort(r.host, r.port), r.password)
158181
if err != nil {
159182
r.logger.Error("failed to connect to RCON", zap.Error(err))
160-
return err
183+
return nil, err
161184
}
162185

163-
r.Conn = conn
164-
165186
// Test the connection
166-
_, err = r.Conn.Execute("/help")
187+
_, err = conn.Execute("/help")
167188
if err != nil {
168189
r.logger.Error("failed to ping RCON", zap.Error(err))
169-
return err
190+
return nil, err
170191
}
171192

172193
r.logger.Info("RCON connection established successfully")
173194

174-
return nil
195+
return conn, nil
175196
})
176197
}
177198

@@ -188,7 +209,8 @@ func (r *RCONConn) Execute(ctx context.Context, command string) (string, error)
188209
r.mutex.RLock()
189210
conn := r.Conn
190211
r.mutex.RUnlock()
191-
if conn == nil {
212+
213+
if lo.IsNil(conn) {
192214
return r.Execute(ctx, command)
193215
}
194216

0 commit comments

Comments
 (0)