85885dd866
Resuming a Sprites task whose sandbox was destroyed upstream returned "sprite not found" and dead-ended the user. Detect the upstream 404 via a typed ErrSpriteNotFound sentinel, mark the reconnect step skipped with a user-facing warning explaining what happened, swap the prepare plan in place to the fresh-provision shape, and continue the launch under a new sandbox name on the same branch. The progress plan is now mutable so the reporter can stream the fresh steps live after the reconnect-then-fresh transition. Only the explicit not-found case triggers fallback; other reconnect failures still surface as before, and the fallback fires at most once per launch.
49 lines
1.4 KiB
Go
49 lines
1.4 KiB
Go
package sprites
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// ErrSpriteNotFound is returned when an upstream Sprites API call indicates the
|
|
// sandbox does not exist. The upstream SDK currently returns plain errors with
|
|
// a "sprite not found: <name>" message for 404 responses; this sentinel lets
|
|
// callers branch on that case without ad-hoc string matching.
|
|
var ErrSpriteNotFound = errors.New("sprite not found")
|
|
|
|
// WrapNotFound wraps err with ErrSpriteNotFound when err looks like an upstream
|
|
// "sprite not found" / 404 response. Other errors are returned unchanged. Pass
|
|
// the returned error to errors.Is(err, ErrSpriteNotFound) to detect the case.
|
|
func WrapNotFound(err error) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if errors.Is(err, ErrSpriteNotFound) {
|
|
return err
|
|
}
|
|
if !looksLikeNotFound(err.Error()) {
|
|
return err
|
|
}
|
|
return fmt.Errorf("%w: %w", ErrSpriteNotFound, err)
|
|
}
|
|
|
|
// IsNotFound reports whether err originated from an upstream "not found"
|
|
// response, even when WrapNotFound has not been applied. Useful for callers
|
|
// that receive a raw upstream error.
|
|
func IsNotFound(err error) bool {
|
|
if err == nil {
|
|
return false
|
|
}
|
|
if errors.Is(err, ErrSpriteNotFound) {
|
|
return true
|
|
}
|
|
return looksLikeNotFound(err.Error())
|
|
}
|
|
|
|
func looksLikeNotFound(msg string) bool {
|
|
lower := strings.ToLower(msg)
|
|
return strings.Contains(lower, "sprite not found") ||
|
|
strings.Contains(lower, "not found")
|
|
}
|