mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
Proper error handling when attempting to remove node when there aren't enough replicas
This commit is contained in:
parent
97915cf5f9
commit
d28a30ebd4
2 changed files with 44 additions and 2 deletions
15
cluster.go
15
cluster.go
|
|
@ -737,7 +737,7 @@ func (c *Cluster) fragSources(to *Cluster, idx *Index) (map[string][]*internal.R
|
|||
// the fragment.
|
||||
srcNodeID, ok := srcNodesByFrag[frag]
|
||||
if !ok {
|
||||
return nil, errors.New("not enough data to perform resize")
|
||||
return nil, errors.New("not enough data to perform resize (replica factor may need to be increased)")
|
||||
}
|
||||
|
||||
src := &internal.ResizeSource{
|
||||
|
|
@ -937,7 +937,11 @@ func (c *Cluster) allNodesReady() bool {
|
|||
func (c *Cluster) handleNodeAction(nodeAction nodeAction) error {
|
||||
j, err := c.generateResizeJob(nodeAction)
|
||||
if err != nil {
|
||||
return err
|
||||
c.logger().Printf("generateResizeJob error: err=%s", err)
|
||||
if err := c.setStateAndBroadcast(ClusterStateNormal); err != nil {
|
||||
c.logger().Printf("setStateAndBroadcast error: err=%s", err)
|
||||
}
|
||||
return c.setStateAndBroadcast(ClusterStateNormal)
|
||||
}
|
||||
|
||||
// j.Run() runs in a goroutine because in the case where the
|
||||
|
|
@ -1702,6 +1706,13 @@ func (c *Cluster) NodeLeave(node *Node) error {
|
|||
return fmt.Errorf("The coordinator node cannot be removed. First, make a different node the new coordinator.")
|
||||
}
|
||||
|
||||
// See if resize job can be generated
|
||||
_, err := c.generateResizeJobByAction(nodeAction{c.nodeByID(node.ID), ResizeJobActionRemove})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.nodeLeave(node)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -545,4 +545,35 @@ func TestClusterResize_RemoveNode(t *testing.T) {
|
|||
t.Fatalf("expected Body '%s' but got '%s'", expBody, strings.TrimSpace(resp.Body))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ErrorRemoveWithoutReplicas", func(t *testing.T) {
|
||||
client0 := m0.Client()
|
||||
|
||||
// Create indexes and frames on one node.
|
||||
if err := client0.CreateIndex(context.Background(), "i", pilosa.IndexOptions{}); err != nil && err != pilosa.ErrIndexExists {
|
||||
t.Fatal(err)
|
||||
} else if err := client0.CreateFrame(context.Background(), "i", "f", pilosa.FrameOptions{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
setBits := ""
|
||||
for i := 0; i < 20; i++ {
|
||||
setBits += fmt.Sprintf("SetBit(rowID=1, frame=\"f\", columnID=%d) ", i*pilosa.SliceWidth)
|
||||
}
|
||||
|
||||
if _, err := m0.Query("i", "", setBits); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
resp := test.MustDo("GET", m1.URL()+fmt.Sprintf("/id"), "")
|
||||
nodeID := resp.Body
|
||||
|
||||
resp = test.MustDo("POST", m0.URL()+fmt.Sprintf("/cluster/resize/remove-node"), fmt.Sprintf(`{"id": "%s"}`, nodeID))
|
||||
expBody := "not enough data to perform resize"
|
||||
if resp.StatusCode != http.StatusInternalServerError {
|
||||
t.Fatalf("expected StatusCode %d but got %d", http.StatusInternalServerError, resp.StatusCode)
|
||||
} else if !strings.Contains(resp.Body, expBody) {
|
||||
t.Fatalf("expected to contain '%s' but got '%s'", expBody, strings.TrimSpace(resp.Body))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue