@@ -22,22 +22,20 @@ import (
22
22
"os"
23
23
"path/filepath"
24
24
"strings"
25
- "sync"
26
25
27
26
"github.com/google/go-cmp/cmp"
28
- "github.com/pkg/errors"
29
-
30
27
native_errors "github.com/haproxytech/client-native/v5/errors"
31
28
"github.com/haproxytech/client-native/v5/misc"
32
29
"github.com/haproxytech/client-native/v5/models"
33
30
"github.com/haproxytech/client-native/v5/runtime/options"
31
+ "github.com/pkg/errors"
32
+ "golang.org/x/sync/singleflight"
34
33
)
35
34
36
35
// Client handles multiple HAProxy clients
37
36
type client struct {
38
- haproxyVersion * HAProxyVersion
39
- options options.RuntimeOptions
40
- runtimes []* SingleRuntime
37
+ options options.RuntimeOptions
38
+ runtimes []* SingleRuntime
41
39
}
42
40
43
41
const (
@@ -104,44 +102,53 @@ func (c *client) GetInfo() (models.ProcessInfos, error) {
104
102
return result , nil
105
103
}
106
104
107
- var versionSync sync.Once //nolint:gochecknoglobals
105
+ var (
106
+ haproxyVersion * HAProxyVersion //nolint:gochecknoglobals
107
+ versionKey = "version" //nolint:gochecknoglobals
108
+ versionSfg = singleflight.Group {} //nolint:gochecknoglobals
109
+ )
108
110
109
111
// GetVersion returns info from the socket
110
112
func (c * client ) GetVersion () (HAProxyVersion , error ) {
111
113
var err error
112
- versionSync .Do (func () {
114
+ if haproxyVersion != nil {
115
+ return * haproxyVersion , nil
116
+ }
117
+ _ , err , _ = versionSfg .Do (versionKey , func () (interface {}, error ) {
113
118
version := & HAProxyVersion {}
114
119
for _ , runtime := range c .runtimes {
115
120
var response string
116
121
response , err = runtime .ExecuteRaw ("show info" )
117
122
if err != nil {
118
- return
123
+ return HAProxyVersion {}, err
119
124
}
120
125
for _ , line := range strings .Split (response , "\n " ) {
121
126
if strings .HasPrefix (line , "Version: " ) {
122
127
err = version .ParseHAProxyVersion (strings .TrimPrefix (line , "Version: " ))
123
128
if err != nil {
124
- return
129
+ return HAProxyVersion {}, err
125
130
}
126
- c . haproxyVersion = version
127
- return
131
+ haproxyVersion = version
132
+ return haproxyVersion , nil
128
133
}
129
134
}
130
135
}
131
- err = fmt .Errorf ("version data not found" )
136
+ err = errors .New ("version data not found" )
137
+ return HAProxyVersion {}, err // it's dereferenced in IsVersionBiggerOrEqual
132
138
})
133
139
if err != nil {
134
140
return HAProxyVersion {}, err
135
141
}
136
142
137
- if c . haproxyVersion == nil {
138
- return HAProxyVersion {}, fmt . Errorf ("version data not found" )
143
+ if haproxyVersion == nil {
144
+ return HAProxyVersion {}, errors . New ("version data not found" )
139
145
}
140
- return * c .haproxyVersion , err
146
+
147
+ return * haproxyVersion , err
141
148
}
142
149
143
150
func (c * client ) IsVersionBiggerOrEqual (minimumVersion * HAProxyVersion ) bool {
144
- return IsBiggerOrEqual (minimumVersion , c . haproxyVersion )
151
+ return IsBiggerOrEqual (minimumVersion , haproxyVersion )
145
152
}
146
153
147
154
// Reloads HAProxy's configuration file. Similar to SIGUSR2. Returns the startup logs.
@@ -152,7 +159,7 @@ func (c *client) Reload() (string, error) {
152
159
return "" , fmt .Errorf ("cannot reload: not connected to a master socket" )
153
160
}
154
161
if ! c .IsVersionBiggerOrEqual (& HAProxyVersion {Major : 2 , Minor : 7 }) {
155
- return "" , fmt .Errorf ("cannot reload: requires HAProxy 2.7 or later" )
162
+ return "" , fmt .Errorf ("cannot reload: requires HAProxy 2.7 or later but current version is %v" , haproxyVersion )
156
163
}
157
164
158
165
for _ , runtime := range c .runtimes {
@@ -229,7 +236,7 @@ func (c *client) AddServer(backend, name, attributes string) error {
229
236
return fmt .Errorf ("no valid runtimes found" )
230
237
}
231
238
if ! c .IsVersionBiggerOrEqual (& HAProxyVersion {Major : 2 , Minor : 6 }) {
232
- return fmt .Errorf ("this operation requires HAProxy 2.6 or later" )
239
+ return fmt .Errorf ("this operation requires HAProxy 2.6 or later but current version is %v" , haproxyVersion )
233
240
}
234
241
for _ , runtime := range c .runtimes {
235
242
err := runtime .AddServer (backend , name , attributes )
0 commit comments