From a2eb24f7d6a0dac907d71ed4000b214e3b6156ae Mon Sep 17 00:00:00 2001 From: Samantha Date: Wed, 17 Aug 2022 14:28:16 -0700 Subject: [PATCH] control: Improve node classification (#37) - Make classification in `NodeIsNew()` less overfit. - Return a clear error when the scaling values in Nomad and Consul are mismatched Resolves #36 Resolves #11 --- cmd/attache-control/main.go | 9 ++++++++- src/redis/client/client.go | 14 +++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/cmd/attache-control/main.go b/cmd/attache-control/main.go index b472e92..fac9126 100644 --- a/cmd/attache-control/main.go +++ b/cmd/attache-control/main.go @@ -153,7 +153,14 @@ func (l *leader) joinOrCreateRedisCluster() error { return nil } - // This should never happen as long as the job and scaling opts match. + clusterNodesCount := len(primaryNodesInCluster) + len(replicaNodesInCluster) + if l.scalingOpts.NodesMissing(clusterNodesCount) == 0 { + // This will only happen when the Nomad job is scaled without a + // corresponding change to the scaling opts in Consul. + return fmt.Errorf("%s Nomad group count was scaled without a corresponding change to scaling opts", l.RedisOpts.NodeAddr) + } + + // This should never happen. return fmt.Errorf("%s couldn't be added to an existing cluster", l.RedisOpts.NodeAddr) } diff --git a/src/redis/client/client.go b/src/redis/client/client.go index d482503..abb4b7d 100644 --- a/src/redis/client/client.go +++ b/src/redis/client/client.go @@ -23,12 +23,20 @@ type Client struct { Client *redis.Client } +// IsNew returns 'true' if the contents of 'CLUSTER INFO' match those expected +// of a node that has never been joined a cluster. 'cluster_state' will be +// 'fail' as a minumum of 3 nodes is required. 'cluster_known_nodes' will be '1' +// (self) since it's never been introduced to other nodes. 'cluster_slots_count' +// and cluster_size' will both be '0' since slots are only assigned as part of +// the inital clustering or during cluster rebalancing. If any of these fields +// holds a different value, 'false' is returned. func (h *Client) IsNew() (bool, error) { - var infoMatchingNewNodes = clusterInfo{"fail", 0, 0, 0, 0, 1, 0, 0, 0, 0, 0} - clusterInfo, err := h.GetClusterInfo() + c, err := h.GetClusterInfo() if err != nil { return false, err - } else if *clusterInfo == infoMatchingNewNodes { + } + + if c.State == "fail" && c.SlotsAssigned == 0 && c.KnownNodes == 1 && c.Size == 0 { return true, nil } else { return false, nil