diff --git a/app.go b/app.go index ebe8eb6989..c0f18dedd0 100644 --- a/app.go +++ b/app.go @@ -25,6 +25,7 @@ import ( v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/patrickmn/go-cache" zerolog "github.com/philip-bui/grpc-zerolog" + "github.com/puzpuzpuz/xsync" zl "github.com/rs/zerolog" "github.com/rs/zerolog/log" ginprometheus "github.com/zsais/go-gin-prometheus" @@ -160,7 +161,7 @@ type Headscale struct { aclPolicy *ACLPolicy aclRules []tailcfg.FilterRule - lastStateChange sync.Map + lastStateChange *xsync.MapOf[time.Time] oidcProvider *oidc.Provider oauth2Config *oauth2.Config @@ -793,18 +794,29 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { func (h *Headscale) setLastStateChangeToNow(namespace string) { now := time.Now().UTC() lastStateUpdate.WithLabelValues("", "headscale").Set(float64(now.Unix())) + if h.lastStateChange == nil { + h.lastStateChange = xsync.NewMapOf[time.Time]() + } h.lastStateChange.Store(namespace, now) } func (h *Headscale) getLastStateChange(namespaces ...string) time.Time { times := []time.Time{} - for _, namespace := range namespaces { - if wrapped, ok := h.lastStateChange.Load(namespace); ok { - lastChange, _ := wrapped.(time.Time) - - times = append(times, lastChange) + // getLastStateChange takes a list of namespaces as a "filter", if no namespaces + // are past, then use the entier list of namespaces and look for the last update + if len(namespaces) > 0 { + for _, namespace := range namespaces { + if lastChange, ok := h.lastStateChange.Load(namespace); ok { + times = append(times, lastChange) + } } + } else { + h.lastStateChange.Range(func(key string, value time.Time) bool { + times = append(times, value) + + return true + }) } sort.Slice(times, func(i, j int) bool { diff --git a/flake.nix b/flake.nix index cbdeaf7fcc..74aa665db7 100644 --- a/flake.nix +++ b/flake.nix @@ -24,7 +24,7 @@ # When updating go.mod or go.sum, a new sha will need to be calculated, # update this if you have a mismatch after doing a change to thos files. - vendorSha256 = "sha256-e3s10NsadWTEk7H7SbEvePhihJ1x2dS9UfIqPNIbJqI="; + vendorSha256 = "sha256-b6qPOO/NmcXsAsSRWZlYXZKyRAF++DsL4TEZzRhQhME="; ldflags = [ "-s" "-w" "-X github.com/juanfont/headscale/cmd/headscale/cli.Version=v${version}" ]; }; diff --git a/go.mod b/go.mod index 69510a5b9a..2d22403209 100644 --- a/go.mod +++ b/go.mod @@ -115,6 +115,7 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect + github.com/puzpuzpuz/xsync v1.2.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 // indirect diff --git a/go.sum b/go.sum index 85c6034cb0..eaf15b8fd9 100644 --- a/go.sum +++ b/go.sum @@ -478,6 +478,8 @@ github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5b github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= github.com/pterm/pterm v0.12.41 h1:e2BRfFo1H9nL8GY0S3ImbZqfZ/YimOk9XtkhoobKJVs= github.com/pterm/pterm v0.12.41/go.mod h1:LW/G4J2A42XlTaPTAGRPvbBfF4UXvHWhC6SN7ueU4jU= +github.com/puzpuzpuz/xsync v1.2.1 h1:faRb6HT9XN3IAhnE7IP0TnPpokPK42qFKXkhQVkWNwM= +github.com/puzpuzpuz/xsync v1.2.1/go.mod h1:K98BYhX3k1dQ2M63t1YNVDanbwUPmBCAhNmVrrxfiGg= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= diff --git a/machine.go b/machine.go index d1ef246c09..db2c63f5b3 100644 --- a/machine.go +++ b/machine.go @@ -9,7 +9,6 @@ import ( "strings" "time" - mapset "github.com/deckarep/golang-set/v2" v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/rs/zerolog/log" "google.golang.org/protobuf/types/known/timestamppb" @@ -469,10 +468,12 @@ func (h *Headscale) isOutdated(machine *Machine) bool { return true } - namespaceSet := mapset.NewSet[string]() - namespaceSet.Add(machine.Namespace.Name) - - lastChange := h.getLastStateChange(namespaceSet.ToSlice()...) + // Get the last update from all headscale namespaces to compare with our nodes + // last update. + // TODO(kradalby): Only request updates from namespaces where we can talk to nodes + // This would mostly be for a bit of performance, and can be calculated based on + // ACLs. + lastChange := h.getLastStateChange() lastUpdate := machine.CreatedAt if machine.LastSuccessfulUpdate != nil { lastUpdate = *machine.LastSuccessfulUpdate