An unchanged process keeps its record, so the node's runtime is not re-created every other cycle (hq issue 210)
The process applier's unchanged path returned an outcome that said nothing about what was written; the loop recorded it like any other, erasing the digest. The next cycle found no record and re-created the daemon, the one after found a record again, and so on: the node's runtime restarted every ten minutes on every machine since it arrived. The outcome now carries the digest forward, as a file's does. The test applies one process three times and asserts the record survives an unchanged apply and no restart is asked.
This commit is contained in:
@@ -256,3 +256,60 @@ func TestAProcessRecordedUnderAPathlikeNameIsRefusedNotRemoved(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// novox/hq 04-ISSUES/210: the node's runtime was re-created — and restarted — on every reconcile,
|
||||
// because the host did not find what it wrote for a process the cycle before. Applying the same
|
||||
// process declaration twice must do no work the second time.
|
||||
func TestAProcessAppliedAgainIsUnchangedAndNotRestarted(t *testing.T) {
|
||||
units, bundles := t.TempDir(), t.TempDir()
|
||||
wasUnits, wasBundles := unitDir, daemonRoot
|
||||
unitDir, daemonRoot = units, bundles
|
||||
t.Cleanup(func() { unitDir, daemonRoot = wasUnits, wasBundles })
|
||||
|
||||
body, digest := anArchive(t, map[string]string{"main.js": "console.log(1)\n"})
|
||||
var commands []string
|
||||
run := func(ctx context.Context, name string, args ...string) (string, error) {
|
||||
commands = append(commands, name+" "+strings.Join(args, " "))
|
||||
return "", nil
|
||||
}
|
||||
d := declare(t, `{"id":"node-tools.runtime","type":"process","name":"node-tools","source":"`+serving(t, body)+
|
||||
`","digest":"`+digest+`","run":["node","main.js"],"env":{"MESH_TOOL_MODULES":"a=/x/index.js"}}`)
|
||||
|
||||
first, state, err := Apply(context.Background(), archHost(t), d, store.State{}, store.OriginDeclared, run, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if o := outcomeOf(first, "node-tools.runtime"); o.Action != "created" {
|
||||
t.Fatalf("first apply: %+v, want created", o)
|
||||
}
|
||||
rec, ok := state.Find("node-tools.runtime")
|
||||
if !ok || rec.Wrote == "" {
|
||||
t.Fatalf("the host did not record what it wrote for the process: %+v", rec)
|
||||
}
|
||||
commands = nil
|
||||
again, state, err := Apply(context.Background(), archHost(t), d, state, store.OriginDeclared, run, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if o := outcomeOf(again, "node-tools.runtime"); o.Action != "unchanged" {
|
||||
t.Errorf("second apply: %+v, want unchanged", o)
|
||||
}
|
||||
for _, c := range commands {
|
||||
if strings.Contains(c, "restart") {
|
||||
t.Errorf("the second apply restarted the process: %v", commands)
|
||||
}
|
||||
}
|
||||
// And the record survives an unchanged apply: the third cycle is unchanged too. This is the
|
||||
// cycle the live mesh showed — created, unchanged, created — before the record was carried.
|
||||
if rec, _ := state.Find("node-tools.runtime"); rec.Wrote == "" {
|
||||
t.Fatalf("an unchanged apply dropped the digest from the record: %+v", rec)
|
||||
}
|
||||
commands = nil
|
||||
third, _, err := Apply(context.Background(), archHost(t), d, state, store.OriginDeclared, run, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if o := outcomeOf(third, "node-tools.runtime"); o.Action != "unchanged" {
|
||||
t.Errorf("third apply: %+v, want unchanged", o)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user