@@ -56,53 +56,56 @@ func (rc *reconnectableClientImpl) reconnect() error {
56
56
}
57
57
}
58
58
59
- func (rc * reconnectableClientImpl ) TCP (addr string ) (net.Conn , error ) {
59
+ // clientDo calls f with the current client.
60
+ // If the client is nil, it will first reconnect.
61
+ // It will also detect if the client is closed, and if so,
62
+ // set it to nil for reconnect next time.
63
+ func (rc * reconnectableClientImpl ) clientDo (f func (Client ) (interface {}, error )) (interface {}, error ) {
60
64
rc .m .Lock ()
61
- defer rc .m .Unlock ()
62
65
if rc .closed {
66
+ rc .m .Unlock ()
63
67
return nil , coreErrs.ClosedError {}
64
68
}
65
69
if rc .client == nil {
66
70
// No active connection, connect first
67
71
if err := rc .reconnect (); err != nil {
72
+ rc .m .Unlock ()
68
73
return nil , err
69
74
}
70
75
}
71
- conn , err := rc .client .TCP (addr )
76
+ client := rc .client
77
+ rc .m .Unlock ()
78
+
79
+ ret , err := f (client )
72
80
if _ , ok := err .(coreErrs.ClosedError ); ok {
73
- // Connection closed, reconnect
74
- if err := rc .reconnect (); err != nil {
75
- return nil , err
81
+ // Connection closed, set client to nil for reconnect next time
82
+ rc .m .Lock ()
83
+ if rc .client == client {
84
+ // This check is in case the client is already changed by another goroutine
85
+ rc .client = nil
76
86
}
77
- return rc .client .TCP (addr )
87
+ rc .m .Unlock ()
88
+ }
89
+ return ret , err
90
+ }
91
+
92
+ func (rc * reconnectableClientImpl ) TCP (addr string ) (net.Conn , error ) {
93
+ if c , err := rc .clientDo (func (client Client ) (interface {}, error ) {
94
+ return client .TCP (addr )
95
+ }); err != nil {
96
+ return nil , err
78
97
} else {
79
- // OK or some other temporary error
80
- return conn , err
98
+ return c .(net.Conn ), nil
81
99
}
82
100
}
83
101
84
102
func (rc * reconnectableClientImpl ) UDP () (HyUDPConn , error ) {
85
- rc .m .Lock ()
86
- defer rc .m .Unlock ()
87
- if rc .closed {
88
- return nil , coreErrs.ClosedError {}
89
- }
90
- if rc .client == nil {
91
- // No active connection, connect first
92
- if err := rc .reconnect (); err != nil {
93
- return nil , err
94
- }
95
- }
96
- conn , err := rc .client .UDP ()
97
- if _ , ok := err .(coreErrs.ClosedError ); ok {
98
- // Connection closed, reconnect
99
- if err := rc .reconnect (); err != nil {
100
- return nil , err
101
- }
102
- return rc .client .UDP ()
103
+ if c , err := rc .clientDo (func (client Client ) (interface {}, error ) {
104
+ return client .UDP ()
105
+ }); err != nil {
106
+ return nil , err
103
107
} else {
104
- // OK or some other temporary error
105
- return conn , err
108
+ return c .(HyUDPConn ), nil
106
109
}
107
110
}
108
111
0 commit comments