@@ -23,19 +23,18 @@ import (
23
23
"os"
24
24
"path/filepath"
25
25
"strings"
26
- "sync"
27
26
28
27
native_errors "github.com/haproxytech/client-native/v6/errors"
29
28
"github.com/haproxytech/client-native/v6/misc"
30
29
"github.com/haproxytech/client-native/v6/models"
31
30
"github.com/haproxytech/client-native/v6/runtime/options"
31
+ "golang.org/x/sync/singleflight"
32
32
)
33
33
34
34
// Client handles multiple HAProxy clients
35
35
type client struct {
36
- haproxyVersion * HAProxyVersion
37
- options options.RuntimeOptions
38
- runtime * SingleRuntime
36
+ options options.RuntimeOptions
37
+ runtime * SingleRuntime
39
38
}
40
39
41
40
const (
@@ -90,50 +89,59 @@ func (c *client) GetInfo() (models.ProcessInfo, error) {
90
89
return result , nil
91
90
}
92
91
93
- var versionSync sync.Once //nolint:gochecknoglobals
92
+ var (
93
+ haproxyVersion * HAProxyVersion //nolint:gochecknoglobals
94
+ versionKey = "version" //nolint:gochecknoglobals
95
+ versionSfg = singleflight.Group {} //nolint:gochecknoglobals
96
+ )
94
97
95
98
// GetVersion returns info from the socket
96
99
func (c * client ) GetVersion () (HAProxyVersion , error ) {
97
100
var err error
98
- versionSync .Do (func () {
101
+ if haproxyVersion != nil {
102
+ return * haproxyVersion , nil
103
+ }
104
+ _ , err , _ = versionSfg .Do (versionKey , func () (interface {}, error ) {
99
105
version := & HAProxyVersion {}
100
106
var response string
101
107
response , err = c .runtime .ExecuteRaw ("show info" )
102
108
if err != nil {
103
- return
109
+ return HAProxyVersion {}, err
104
110
}
105
111
for _ , line := range strings .Split (response , "\n " ) {
106
112
if strings .HasPrefix (line , "Version: " ) {
107
113
err = version .ParseHAProxyVersion (strings .TrimPrefix (line , "Version: " ))
108
114
if err != nil {
109
- return
115
+ return HAProxyVersion {}, err
110
116
}
111
- c . haproxyVersion = version
112
- return
117
+ haproxyVersion = version
118
+ return HAProxyVersion {}, err
113
119
}
114
120
// Starting with HAProxy 3.0, there is no more "Version:" prefix.
115
121
if len (line ) > 0 && line [0 ] >= '3' && line [0 ] <= '9' {
116
122
err = version .ParseHAProxyVersion (line )
117
123
if err == nil {
118
- c . haproxyVersion = version
124
+ haproxyVersion = version
119
125
}
120
- return
126
+ return HAProxyVersion {}, err
121
127
}
122
128
}
123
129
err = errors .New ("version data not found" )
130
+ return HAProxyVersion {}, err // it's dereferenced in IsVersionBiggerOrEqual
124
131
})
125
132
if err != nil {
126
133
return HAProxyVersion {}, err
127
134
}
128
135
129
- if c . haproxyVersion == nil {
136
+ if haproxyVersion == nil {
130
137
return HAProxyVersion {}, errors .New ("version data not found" )
131
138
}
132
- return * c .haproxyVersion , err
139
+
140
+ return * haproxyVersion , err
133
141
}
134
142
135
143
func (c * client ) IsVersionBiggerOrEqual (minimumVersion * HAProxyVersion ) bool {
136
- return IsBiggerOrEqual (minimumVersion , c . haproxyVersion )
144
+ return IsBiggerOrEqual (minimumVersion , haproxyVersion )
137
145
}
138
146
139
147
// Reloads HAProxy's configuration file. Similar to SIGUSR2. Returns the startup logs.
@@ -144,7 +152,7 @@ func (c *client) Reload() (string, error) {
144
152
return "" , errors .New ("cannot reload: not connected to a master socket" )
145
153
}
146
154
if ! c .IsVersionBiggerOrEqual (& HAProxyVersion {Major : 2 , Minor : 7 }) {
147
- return "" , errors . New ("cannot reload: requires HAProxy 2.7 or later" )
155
+ return "" , fmt . Errorf ("cannot reload: requires HAProxy 2.7 or later but current version is %v" , haproxyVersion )
148
156
}
149
157
150
158
output , err := c .runtime .ExecuteMaster ("reload" )
@@ -218,7 +226,7 @@ func (c *client) AddServer(backend, name, attributes string) error {
218
226
return errors .New ("no valid runtime found" )
219
227
}
220
228
if ! c .IsVersionBiggerOrEqual (& HAProxyVersion {Major : 2 , Minor : 6 }) {
221
- return errors . New ("this operation requires HAProxy 2.6 or later" )
229
+ return fmt . Errorf ("this operation requires HAProxy 2.6 or later but current version is %v" , haproxyVersion )
222
230
}
223
231
err := c .runtime .AddServer (backend , name , attributes )
224
232
if err != nil {
0 commit comments