Fix incorrect handling of gen.SupervisorStrategyRestartTransient restart strategy

master
Taras Halturin 2023-04-25 12:22:38 +02:00
parent ea6f5751c2
commit 2e85c20042
No known key found for this signature in database
GPG Key ID: 4949A906AB2FE101
4 changed files with 43 additions and 33 deletions

View File

@ -225,7 +225,7 @@ func startChild(supervisor Process, name string, child ProcessBehavior, opts Pro
process, err := supervisor.Spawn(name, opts, child, args...)
if err != nil {
panic(err)
panic(err.Error())
}
supervisor.Link(process.Self())
@ -321,13 +321,16 @@ func handleMessageExit(p Process, exit ProcessGracefulExitRequest, spec *Supervi
}
spec.Children[i].process = nil
if child.Self() == terminated {
if haveToDisableChild(spec.Strategy.Restart, reason) {
spec.Children[i].state = supervisorChildStateDisabled
} else {
spec.Children[i].state = supervisorChildStateStart
}
if haveToDisableChild(spec.Strategy.Restart, reason) {
spec.Children[i].state = supervisorChildStateDisabled
break
}
if spec.Children[i].state == supervisorChildStateDisabled {
continue
}
spec.Children[i].state = supervisorChildStateStart
if child.Self() == terminated {
if len(spec.Children) == i+1 && len(wait) == 0 {
// it was the last one. nothing to waiting for
startChildren(p, spec)
@ -335,11 +338,6 @@ func handleMessageExit(p Process, exit ProcessGracefulExitRequest, spec *Supervi
continue
}
if haveToDisableChild(spec.Strategy.Restart, "restart") {
spec.Children[i].state = supervisorChildStateDisabled
} else {
spec.Children[i].state = supervisorChildStateStart
}
child.Exit("restart")
wait = append(wait, child.Self())
@ -357,6 +355,7 @@ func handleMessageExit(p Process, exit ProcessGracefulExitRequest, spec *Supervi
spec.Children[i].process = nil
if haveToDisableChild(spec.Strategy.Restart, reason) {
spec.Children[i].state = supervisorChildStateDisabled
break
} else {
spec.Children[i].state = supervisorChildStateStart
}
@ -421,6 +420,18 @@ func handleMessageExit(p Process, exit ProcessGracefulExitRequest, spec *Supervi
}
}
}
// check if all children are disabled. stop this process with reason "normal"
shouldStop := true
for i := range spec.Children {
if spec.Children[i].state == supervisorChildStateDisabled {
continue
}
shouldStop = false
break
}
if shouldStop {
p.Exit("normal")
}
return wait
}

View File

@ -196,7 +196,6 @@ func (tr *testRaft) HandleSerial(process *gen.RaftProcess, ref etf.Ref, serial u
return gen.RaftStatusOK
}
func (tr *testRaft) HandleCancel(process *gen.RaftProcess, ref etf.Ref, reason string) gen.RaftStatus {
fmt.Println("CCC cancel", ref, reason)
return gen.RaftStatusOK
}

View File

@ -157,8 +157,8 @@ func TestSupervisorOneForAll(t *testing.T) {
testCases = []ChildrenTestCase{
{
reason: "normal",
statuses: []string{"empty", "new", "new"},
events: 5, // waiting for 3 terminates and 2 starts
statuses: []string{"empty", "old", "old"},
events: 1, // waiting for 1 terminate
},
{
reason: "abnormal",
@ -167,12 +167,12 @@ func TestSupervisorOneForAll(t *testing.T) {
},
{
reason: "shutdown",
statuses: []string{"empty", "new", "empty"},
events: 3, // waiting for 2 terminates and 1 start
statuses: []string{"empty", "old", "empty"},
events: 1, // waiting for 1 terminate
},
}
for i := range children {
fmt.Printf("... stopping child %d with '%s' reason and waiting for restarting all of them ... ", i+1, testCases[i].reason)
fmt.Printf("... stopping child %d with '%s' reason and waiting for restarting all of them if reason != normal ... ", i+1, testCases[i].reason)
processSV.Send(children[i], testCases[i].reason) // stopping child
if children1, err := waitNeventsSupervisorChildren(sv.ch, testCases[i].events, children); err != nil {
@ -213,18 +213,18 @@ func TestSupervisorOneForAll(t *testing.T) {
testCases = []ChildrenTestCase{
{
reason: "normal",
statuses: []string{"empty", "empty", "empty"},
events: 3, // waiting for 3 terminates
statuses: []string{"empty", "old", "old"},
events: 1, // waiting for 1 terminate
},
{
reason: "abnormal",
statuses: []string{"empty", "empty", "empty"},
events: 3, // waiting for 3 terminates
statuses: []string{"old", "empty", "old"},
events: 1, // waiting for 1 terminate
},
{
reason: "shutdown",
statuses: []string{"empty", "empty", "empty"},
events: 3, // waiting for 3 terminate
statuses: []string{"old", "old", "empty"},
events: 1, // waiting for 1 terminate
},
}
@ -241,7 +241,7 @@ func TestSupervisorOneForAll(t *testing.T) {
fmt.Println("OK")
}
fmt.Printf("... stopping child %d with '%s' reason and waiting for restarting all of them ... ", i+1, testCases[i].reason)
fmt.Printf("... stopping child %d with '%s' reason and no one should be restarted ... ", i+1, testCases[i].reason)
processSV.Send(children[i], testCases[i].reason) // stopping child
if children1, err := waitNeventsSupervisorChildren(sv.ch, testCases[i].events, children); err != nil {
@ -258,7 +258,7 @@ func TestSupervisorOneForAll(t *testing.T) {
fmt.Printf("Stopping supervisor 'testSupervisorTemporary' (%s)... ", gen.SupervisorStrategyRestartTemporary)
processSV.Exit("x")
if children1, err := waitNeventsSupervisorChildren(sv.ch, 0, children); err != nil {
if children1, err := waitNeventsSupervisorChildren(sv.ch, len(children)-testCases[i].events, children); err != nil {
t.Fatal(err)
} else {
statuses := []string{"empty", "empty", "empty"}

View File

@ -165,8 +165,8 @@ func TestSupervisorRestForOne(t *testing.T) {
},
{
reason: "normal",
statuses: []string{"old", "empty", "new"},
events: 3, // waiting for 2 terminates and 1 starts
statuses: []string{"old", "empty", "old"},
events: 1, // waiting for 1 terminate
},
{
reason: "shutdown",
@ -175,7 +175,7 @@ func TestSupervisorRestForOne(t *testing.T) {
},
}
for i := range children {
fmt.Printf("... stopping child %d with '%s' reason and waiting for restarting rest of them ... ", i+1, testCases[i].reason)
fmt.Printf("... stopping child %d with '%s' reason and waiting for restarting if reason != normal ... ", i+1, testCases[i].reason)
processSV.Send(children[i], testCases[i].reason) // stopping child
if children1, err := waitNeventsSupervisorChildren(sv.ch, testCases[i].events, children); err != nil {
@ -216,13 +216,13 @@ func TestSupervisorRestForOne(t *testing.T) {
testCases = []ChildrenTestCase{
{
reason: "normal",
statuses: []string{"empty", "empty", "empty"},
events: 3, // waiting for 3 terminates
statuses: []string{"empty", "old", "old"},
events: 1, // waiting for 1 terminate
},
{
reason: "abnormal",
statuses: []string{"old", "empty", "empty"},
events: 2, // waiting for 2 terminates
statuses: []string{"old", "empty", "old"},
events: 1, // waiting for 1 terminate
},
{
reason: "shutdown",