Documentation
¶
Overview ¶
Package scriptguard is what stops a managed-script run apart from the script's own logic, and what that stop is recorded as: the memory budget a run is measured against at every host call (#1861), and the cause a failed run is recorded under -- the script's, an upstream that did not answer, or the budget -- which decides whether running it again is expected to succeed (#1859).
It knows the Starlark value model, and nothing about runs, stores or workers: the engine in internal/platform/scriptrun calls into it at its host bindings. The waits the host makes on an upstream that asked it to come back later are internal/upstreamretry's.
Index ¶
- Variables
- func Cause(err error) string
- func FormatBytes(n int64) string
- func Size(v starlark.Value) int64
- type LastUpstream
- type Meter
- func (m *Meter) Called(tool string)
- func (m *Meter) Check(thread *starlark.Thread, at string) error
- func (m *Meter) Handed(thread *starlark.Thread, at string, result starlark.Value) error
- func (m *Meter) Holding(n int64)
- func (m *Meter) Peak() int64
- func (m *Meter) Settle(globals starlark.StringDict) error
- type TransientError
- type UpstreamError
Constants ¶
This section is empty.
Variables ¶
var ErrMemoryBudget = errors.New("script exceeded its memory budget")
ErrMemoryBudget marks a run stopped for holding more memory than its budget.
var Fail = starlark.NewBuiltin("fail", func( thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple, ) (starlark.Value, error) { retryable := false rest := make([]starlark.Tuple, 0, len(kwargs)) for _, kv := range kwargs { if name, _ := starlark.AsString(kv[0]); name != "retryable" { rest = append(rest, kv) continue } flag, ok := kv[1].(starlark.Bool) if !ok { return nil, fmt.Errorf("fail: retryable must be True or False, not %s", kv[1].Type()) } retryable = bool(flag) } _, err := starlark.Call(thread, starlark.Universe["fail"], args, rest) // Call reports the universe's failure as an EvalError of its own frame; // the failure itself is what this builtin raises, so the backtrace the // author reads names one fail() call, as before. var evalErr *starlark.EvalError if errors.As(err, &evalErr) && evalErr.Unwrap() != nil { err = evalErr.Unwrap() } if retryable { return nil, NewTransientError(err) } return nil, err })
Fail is Starlark's fail(*args, sep=" ") with one more keyword (#1935): retryable=True declares the failure temporary, so the run is recorded as retryable (cause transient) rather than as the script's own. Everything else is the universe's fail, unchanged, so a script that never passes retryable= fails exactly as it did.
Functions ¶
func Cause ¶
Cause is the cause a run that failed with err is recorded under: memory for a budget it exceeded, upstream for an upstream that was unavailable or answered the script's last call with a failure, transient for a failure the script declared temporary, and the script's own for every other failure the interpreter reports.
func FormatBytes ¶
FormatBytes renders a size the way the budget is configured: "128 MiB".
Types ¶
type LastUpstream ¶ added in v1.137.1
type LastUpstream struct {
// contains filtered or unexported fields
}
LastUpstream keeps whether the upstream answered a run's most recent tool call with a failure (#1935). The api gateway hands a script a 5xx as data, so a script that checks the status and calls fail() -- the only thing it can do -- fails because of that answer, and is recorded as the upstream's rather than told the next run fails the same way. The zero value holds none.
func (*LastUpstream) Attribute ¶ added in v1.137.1
func (l *LastUpstream) Attribute(err error, note func(string), keep ...error) error
Attribute returns err as the upstream's when the run's latest call was answered with a failure and err is otherwise the script's own, handing note the line the run's log records why; err unchanged otherwise. A limit a caller names in keep, a memory stop and a failure already classified keep theirs.
func (*LastUpstream) Clear ¶ added in v1.137.1
func (l *LastUpstream) Clear()
Clear records a latest call that got no upstream answer at all.
type Meter ¶
type Meter struct {
// contains filtered or unexported fields
}
Meter measures what one run holds against its budget and keeps the peak. It is used from the interpreter's goroutine only, at host calls.
func NewMeter ¶
NewMeter returns a meter for a run allowed budget bytes; zero or less sets no budget and still measures the peak.
func (*Meter) Called ¶
Called counts one tool result the run was handed, for the refusal to say where its memory came from.
func (*Meter) Check ¶
Check measures what the thread holds at the host call named at, and refuses once it is over the budget. It walks the thread when the last walk is older than walkEvery, or when the last estimate plus what the process has allocated since could be over the budget. A nil meter measures nothing.
func (*Meter) Handed ¶
Handed adds a value a host call is about to hand the script to the estimate, and refuses when it takes the run over its budget.
func (*Meter) Holding ¶
Holding records how much the run holds outside the interpreter, replacing the last figure. The figure is measured, not estimated, so it counts toward the peak.
func (*Meter) Settle ¶
func (m *Meter) Settle(globals starlark.StringDict) error
Settle measures what the module's globals hold when the script ends, so the peak includes what it built after its last host call, and refuses when that is over the budget: a run that ended holding more than it is allowed failed its budget as surely as one stopped at a host call.
type TransientError ¶ added in v1.137.1
type TransientError struct {
// contains filtered or unexported fields
}
TransientError is a failure the script declared temporary with fail(..., retryable=True) (#1935): its author knows the condition it stopped on is outside the script, such as data that has not arrived yet.
func NewTransientError ¶ added in v1.137.1
func NewTransientError(err error) *TransientError
NewTransientError marks the failure fail() raised as temporary.
func (*TransientError) Error ¶ added in v1.137.1
func (e *TransientError) Error() string
Error returns fail()'s own text, which is what the author reads.
func (*TransientError) Unwrap ¶ added in v1.137.1
func (e *TransientError) Unwrap() error
Unwrap returns the failure fail() raised.
type UpstreamError ¶
type UpstreamError struct {
// Tool is the tool the script called.
Tool string
// contains filtered or unexported fields
}
UpstreamError is a tool call that failed because the upstream it reached was unavailable: it timed out, dropped the connection, or could not be reached, or the run's deadline arrived while the host was waiting to retry it. The same call made later is expected to succeed, so a run it ends is recorded as retryable.
func NewUpstreamError ¶
func NewUpstreamError(tool string, err error) *UpstreamError
NewUpstreamError wraps the failure of a call to tool as an upstream one.
func (*UpstreamError) Error ¶
func (e *UpstreamError) Error() string
Error returns the tool's own failure text, which is what the author reads.
func (*UpstreamError) Unwrap ¶
func (e *UpstreamError) Unwrap() error
Unwrap returns the failure the tool reported.