mirror of https://github.com/hashicorp/consul
metadata: memoize the parsed build versions (#22113)
There will only be a small set of consul build versions that a single consul server will witness. Inside of metadata.IsConsulServer we use a very expensive function in the hashicorp/go-version library to parse these into read-only *version.Version structs all over Consul. Memoize these in a package cache map. Likely the thing will only have like 2 keys in it ever over the life of the process.pull/22103/head^2
parent
3e0c098890
commit
00d74abc4a
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
metadata: memoize the parsed build versions
|
||||
```
|
|
@ -4,12 +4,48 @@
|
|||
package metadata
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/hashicorp/serf/serf"
|
||||
)
|
||||
|
||||
type versionTuple struct {
|
||||
Value *version.Version
|
||||
Err error
|
||||
}
|
||||
|
||||
var versionCache sync.Map // string->versionTuple
|
||||
|
||||
// Build extracts the Consul version info for a member.
|
||||
func Build(m *serf.Member) (*version.Version, error) {
|
||||
str := versionFormat.FindString(m.Tags["build"])
|
||||
build := m.Tags["build"]
|
||||
|
||||
ok, v, err := getMemoizedBuildVersion(build)
|
||||
if ok {
|
||||
return v, err
|
||||
}
|
||||
|
||||
v, err = parseBuildAsVersion(build)
|
||||
|
||||
versionCache.Store(build, versionTuple{Value: v, Err: err})
|
||||
|
||||
return v, err
|
||||
}
|
||||
|
||||
func getMemoizedBuildVersion(build string) (bool, *version.Version, error) {
|
||||
rawTuple, ok := versionCache.Load(build)
|
||||
if !ok {
|
||||
return false, nil, nil
|
||||
}
|
||||
tuple, ok := rawTuple.(versionTuple)
|
||||
if !ok {
|
||||
return false, nil, nil
|
||||
}
|
||||
return true, tuple.Value, tuple.Err
|
||||
}
|
||||
|
||||
func parseBuildAsVersion(build string) (*version.Version, error) {
|
||||
str := versionFormat.FindString(build)
|
||||
return version.NewVersion(str)
|
||||
}
|
||||
|
|
|
@ -127,11 +127,6 @@ func IsConsulServer(m serf.Member) (bool, *Server) {
|
|||
}
|
||||
}
|
||||
|
||||
buildVersion, err := Build(&m)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
wanJoinPort := 0
|
||||
wanJoinPortStr, ok := m.Tags["wan_join_port"]
|
||||
if ok {
|
||||
|
@ -180,6 +175,11 @@ func IsConsulServer(m serf.Member) (bool, *Server) {
|
|||
|
||||
addr := &net.TCPAddr{IP: m.Addr, Port: port}
|
||||
|
||||
buildVersion, err := Build(&m)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
parts := &Server{
|
||||
Name: m.Name,
|
||||
ShortName: strings.TrimSuffix(m.Name, "."+datacenter),
|
||||
|
|
Loading…
Reference in New Issue