ENG-8, ENG-9, ENG-11: a failed pull from a store is tried again once per settled of the store's holder, heard on every node, and the failed have says whom it waits on and what triggered the last retry (design 51, issue 1966; needs mesh-sdk request R1, R2)

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 11:49:44 +01:00
parent 3eef84d979
commit 2a71a8ff76
8 changed files with 467 additions and 17 deletions
+31 -4
View File
@@ -3481,16 +3481,17 @@ func ensureImage(ctx context.Context, cri, image string, run Runner) error {
// already hold — built here, or handed over. There is no registry that answers for it, so
// pulling would fail somewhere that names a network problem instead of a missing image.
if strings.HasPrefix(image, "sha256:") {
return &PullError{Image: image, Err: fmt.Errorf(
return &PullError{Image: image, Started: time.Now(), Err: fmt.Errorf(
"image %s is not on this machine, and an image named by its own digest cannot be "+
"fetched: nothing serves it. Build it here, or load it, before applying this",
image)}
}
started := time.Now()
if _, err := run(ctx, cri, "pull", image); err != nil {
return &PullError{Image: image, Err: fmt.Errorf("pulling image %s: %w", image, err)}
return &PullError{Image: image, Started: started, Err: fmt.Errorf("pulling image %s: %w", image, err)}
}
if _, err := run(ctx, cri, "image", "inspect", image); err != nil {
return &PullError{Image: image, Err: fmt.Errorf("image %s is not present after pulling it: %w", image, err)}
return &PullError{Image: image, Started: time.Now(), Err: fmt.Errorf("image %s is not present after pulling it: %w", image, err)}
}
return nil
}
@@ -4405,7 +4406,33 @@ func pullFirst(ctx context.Context, ordered []declaration.Resource, d *declarati
// pull from another failed apply (ENG-8).
type PullError struct {
Image string
Err error
// Started is when the pull began, which the node agent compares with when a store's holder settled (ENG-11).
Started time.Time
Err error
}
// PullErrors are the pull errors of every failure an apply reports, the first among them and the rest in Failures, in the
// order they happened: what the node agent tells a failed pull from another failed apply by (ENG-8). Nil for an error
// that is no apply's, or whose failures met none.
func PullErrors(err error) []*PullError {
var out []*PullError
var e *Error
if errors.As(err, &e) {
for _, f := range e.Failures {
var p *PullError
if errors.As(f.Err, &p) {
out = append(out, p)
}
}
if len(out) > 0 {
return out
}
}
var p *PullError
if errors.As(err, &p) {
out = append(out, p)
}
return out
}
func (e *PullError) Error() string { return e.Err.Error() }