Say a registry came back only when the call worked, and retry from toRetry's set (issue 457 review)
mesh/merge-gate pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without …
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery delivered

The streaming blob PUT is left unwaited, with why, since its body cannot be
read twice and the POST before it already waited.
This commit is contained in:
2026-10-11 11:05:30 +02:00
parent 7758301444
commit 83ce19b9c0
3 changed files with 19 additions and 7 deletions
+6 -5
View File
@@ -289,21 +289,23 @@ func retryPlan(ctx context.Context, open *stores, id string) (string, error) {
}
}
// Settled from the build records before anything is judged (novox/hq issue 457): a build of the tier
// that failed after the plan did is as failed as the one that failed it.
// that failed after the plan did is as failed as the one that failed it. What toRetry says is the
// failed set every step below works from.
var failed []string
if p.Tier < len(p.Tiers) {
recorded, byID, err := recordsOfAsked(ctx, inv, &p, p.Tiers[p.Tier])
if err != nil {
return "", err
}
toRetry(&p, recorded, byID)
failed = toRetry(&p, recorded, byID)
}
if err := retryRefusal(p, plans); err != nil {
return "", err
}
if again := unjudgedAtGate(p); len(failedIn(p)) == 0 && len(again) > 0 {
if again := unjudgedAtGate(p); len(failed) == 0 && len(again) > 0 {
return retryTierWhole(ctx, open, &p, again)
}
if len(failedIn(p)) == 0 {
if len(failed) == 0 {
return retryRollouts(ctx, open, &p)
}
entries, err := inv.Catalogued(ctx)
@@ -314,7 +316,6 @@ func retryPlan(ctx context.Context, open *stores, id string) (string, error) {
for _, e := range entries {
byName[e.Manifest.Module] = e
}
failed := failedIn(p)
var asked []string
for _, m := range failed {
askModule(ctx, &p, m, byName)
+5
View File
@@ -429,6 +429,11 @@ func (r Registry) copyBlob(ctx context.Context, src *source, where upstream, dig
if response.ContentLength > 0 {
put.ContentLength = response.ContentLength
}
// **Not waited for if refused** (novox/hq issue 457): the body streams from upstream and cannot be
// read twice, so a registry held still between the POST above and this PUT fails the copy with
// "its body cannot be read twice" rather than waiting. Accepted: the POST a moment before already
// waited the registry out, so the window is the length of one upstream fetch, and the build fails
// loudly, to be asked again, rather than buffering every base blob in memory.
done, err := r.client().Do(put)
if err != nil {
return fmt.Errorf("cannot upload blob %s: %w", digest, err)
+8 -2
View File
@@ -74,8 +74,14 @@ func waitForRegistry(ctx context.Context, address, what string, try func() error
}
pause = min(pause*2, registryMostPause)
if err = try(); !refused(err) {
tell("registry", "%s: the registry at %s answers again after %s; the build goes on", what, address,
time.Since(started).Round(time.Millisecond))
// Said as it is: the registry answering is only the build going on when the call worked.
if err == nil {
tell("registry", "%s: the registry at %s answers again after %s; the build goes on", what, address,
time.Since(started).Round(time.Millisecond))
} else {
tell("registry", "%s: the registry at %s no longer refuses after %s, and answered with: %v", what,
address, time.Since(started).Round(time.Millisecond), err)
}
return err
}
}