diff --git a/.changelog/22113.txt b/.changelog/22113.txt new file mode 100644 index 0000000000..c97fff1a4a --- /dev/null +++ b/.changelog/22113.txt @@ -0,0 +1,3 @@ +```release-note:improvement +metadata: memoize the parsed build versions +``` diff --git a/agent/metadata/build.go b/agent/metadata/build.go index 76a432d9a3..880132b9db 100644 --- a/agent/metadata/build.go +++ b/agent/metadata/build.go @@ -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) } diff --git a/agent/metadata/server.go b/agent/metadata/server.go index 2e626787bd..19dba6e2cc 100644 --- a/agent/metadata/server.go +++ b/agent/metadata/server.go @@ -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),