The indexer takes the engine's want as its build only while the apply is in progress (issue 1921)
mesh/check being carried to e3735da928f4 on 8c67adaf9136 | from abe9ea3796ea
mesh/delivery merged: source.main moved to novox/mesh-delivery@8c67adaf9136
mesh/check being carried to e3735da928f4 on 8c67adaf9136 | from abe9ea3796ea
mesh/delivery merged: source.main moved to novox/mesh-delivery@8c67adaf9136
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
@@ -74,6 +74,9 @@ func TestTheTrunkIsTheDirectoriesTheForgeListsTrees(t *testing.T) { // 1900/AC3
|
||||
for _, row := range []struct{ name, answer, want string }{
|
||||
{"replacing: runs old, want new and self", `{"runs":{"fp":"src2:old"},"want":{"fp":"src2:new","self":true}}`, "src2:new"},
|
||||
{"a want the node does not compose", `{"runs":{"fp":"src2:old"},"want":{"fp":"src2:new"}}`, "src2:old"},
|
||||
{"replacing: the apply of the want failed or is held", `{"runs":{"fp":"src2:old"},"want":{"fp":"src2:new","self":true},"attempt":{"fp":"src2:new","held":true}}`, "src2:old"},
|
||||
{"replacing: an attempt of another build", `{"runs":{"fp":"src2:old"},"want":{"fp":"src2:new","self":true},"attempt":{"fp":"src2:older"}}`, "src2:new"},
|
||||
{"the want already runs", `{"runs":{"fp":"src2:new"},"want":{"fp":"src2:new","self":true}}`, "src2:new"},
|
||||
{"a removed want", `{"runs":{"fp":"src2:old"},"want":{"fp":"src2:new","self":true,"removed":true}}`, "src2:old"},
|
||||
{"no build runs yet, want self", `{"want":{"fp":"src2:new","self":true}}`, "src2:new"},
|
||||
} {
|
||||
|
||||
@@ -30,15 +30,26 @@ func ownBuildVia(call toolCaller, node string) func(ctx context.Context) (string
|
||||
Self bool `json:"self"`
|
||||
Removed bool `json:"removed"`
|
||||
} `json:"want"`
|
||||
// Attempt is the engine's last apply that did not end running (failed, or held), with the build it was of.
|
||||
Attempt *struct {
|
||||
FP string `json:"fp"`
|
||||
} `json:"attempt"`
|
||||
}
|
||||
if err := json.Unmarshal(raw, &a); err != nil {
|
||||
return "", fmt.Errorf("the answer of %s is not a composition: %w", compositionVerb, err)
|
||||
}
|
||||
// While the engine replaces the indexer, this process is the successor: what runs still names the old build, and the want,
|
||||
// composed by the node itself (self), names this one. The start fixes that build (quick fix, ADR 0639 §7: nothing is learnt
|
||||
// later and nothing waits on a timer); a process of the old build that is started again in that window would take it too.
|
||||
if a.Want != nil && a.Want.Self && !a.Want.Removed && a.Want.FP != "" {
|
||||
return a.Want.FP, nil
|
||||
// While the engine's apply of the want is in progress (what runs still names the old build, the want names another, and no
|
||||
// attempt names that want as failed or held), this process is the successor and fixes the want's build. self is the node's
|
||||
// standing way of composing the module, not a mark of this process, so it is not enough alone: an old process started again
|
||||
// while the want names a successor that does not run (its apply failed or is held) takes what runs. The start fixes the
|
||||
// build once (quick fix, ADR 0639 §7: nothing is learnt later, nothing waits on a timer); the thorough form is the
|
||||
// engine passing each process the fingerprint it starts it with.
|
||||
running := ""
|
||||
if a.Runs != nil {
|
||||
running = a.Runs.FP
|
||||
}
|
||||
if w := a.Want; w != nil && w.Self && !w.Removed && w.FP != "" && w.FP != running && (a.Attempt == nil || a.Attempt.FP != w.FP) {
|
||||
return w.FP, nil
|
||||
}
|
||||
if a.Runs == nil || a.Runs.FP == "" {
|
||||
return "", errors.New("the engine says no fingerprint of the indexer runs")
|
||||
|
||||
Reference in New Issue
Block a user