Files
mesh-delivery/sdk/buildstep/passing.go
T

59 lines
2.8 KiB
Go

package buildstep
import (
"errors"
"fmt"
"strings"
)
// Passing is a fault of the network between a build node and what it reaches (a name lookup, a timeout, a reset
// connection, a forge's sshd refusing a burst, a store that does not answer), not of the source or the toolchain. A
// build module wraps it, and the shared runner then writes the step again and settles its ask with a delayed nak, up to
// AskRuns runs (ADR 0664 §1, §2). Any other error ends the step failed at once.
type Passing struct{ Err error }
func (p *Passing) Error() string { return p.Err.Error() }
func (p *Passing) Unwrap() error { return p.Err }
// IsPassing says err is, or wraps, a Passing.
func IsPassing(err error) bool {
var p *Passing
return errors.As(err, &p)
}
// HolderSilentWords opens the words of a HolderSilent, so PassingCause reads them from a step's reason too.
const HolderSilentWords = "the holder is silent"
// HolderSilent is a seat verb that answered "no responders" while the assigner names a holder of the seat: its tool
// runner is being replaced, a moment later it answers. It is a Passing fault (ADR 0664 §1); a seat nothing holds is not.
type HolderSilent struct{ Seat, Holder, Node string }
func (h *HolderSilent) Error() string {
return fmt.Sprintf("%s: seat %s, held by %s on %s, answered no responders", HolderSilentWords, h.Seat, h.Holder, h.Node)
}
// Unwrap makes a HolderSilent a Passing.
func (h *HolderSilent) Unwrap() error { return &Passing{Err: errors.New(h.Error())} }
// passingWords are the words of a network that did not answer, lower-cased: go's and git's (a lookup, a timeout, a refused or
// reset connection, ssh's key exchange cut by a forge's per-source penalty) and npm's error codes. "no responders" alone is not
// one: it is the same for a seat nothing holds (HolderSilent is the case a holder is named).
var passingWords = []string{"i/o timeout", "no such host", "temporary failure in name resolution", "connection refused",
"connection reset", "tls handshake timeout", "network is unreachable", "no route to host", "lookup ", "kex_exchange_identification", "connection closed by",
"could not resolve host", "client.timeout", "operation timed out", "connection timed out", "eai_again", "etimedout", "econnreset", "econnrefused", "enotfound", strings.ToLower(HolderSilentWords)}
// PassingCause says words (a tool's output or a step's reason) are those of a transport fault.
func PassingCause(words string) bool {
words = strings.ToLower(words)
for _, w := range passingWords {
if strings.Contains(words, w) {
return true
}
}
return false
}
// TransportFaultWords open the reason of a step that ended failed after its runs met a transport fault (the asker says them,
// "a transport fault on 3 runs (nodes): cause"): a reader tells that end from a fault of the source by them (ADR 0664 §3).
const TransportFaultWords = "a transport fault on "