Documentation
¶
Overview ¶
Package script is Atlas's in-process worker for polyglot script tasks (PowerShell, Python, JavaScript — ADR-0047). A script task compiles to a job carrying the language's reserved job type (compiler.PwshJobType / PythonJobType / JsJobType); this worker subscribes to a type via a job.Runner and for each job runs the script off the processor goroutine — after fsync — through an Exec, then writes the script's result back into the instance as the task's result variable.
Keeping the interpreter here, not in an engine behavior, is what lets a general -purpose language run without breaking the engine's invariants: the processor stays allocation-free (I1) and side-effect-free on the recovery path (I4), and the result is frozen into the job completion so replay re-applies it verbatim (I6). It mirrors the DMN worker (ADR-0014): one handler per language serves every deployed process, resolving each job's script from the compiled process. The handler itself is language-agnostic; only the Exec differs per language.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( PowerShell = Lang{ Name: "powershell", JobType: compiler.PwshJobTypeIndex, Bin: "pwsh", Args: func(b string) []string { return []string{"-NoProfile", "-NonInteractive", "-Command", b} }, Wrap: powershellBootstrap, } Python = Lang{ Name: "python", JobType: compiler.PythonJobTypeIndex, Bin: "python3", Args: func(b string) []string { return []string{"-c", b} }, Wrap: pythonBootstrap, } JavaScript = Lang{ Name: "javascript", JobType: compiler.JsJobTypeIndex, Bin: "node", Args: func(b string) []string { return []string{"-e", b} }, Wrap: javascriptBootstrap, } )
The three supported languages. Adding one is a new Lang here plus its reserved job type in the compiler — the worker, engine behavior, and recovery are shared.
var Langs = []Lang{PowerShell, Python, JavaScript}
Langs is every supported language, in a stable order.
Functions ¶
func Handler ¶
func Handler(store state.Reader, lookup ProcessLookup, exec Exec) job.OutputHandler
Handler builds a job handler that runs a script task in one language. Register it with a job.Runner via HandleWithOutput for that language's reserved job type (e.g. compiler.PwshJobTypeIndex); the runner then pulls activatable script jobs, and for each the handler:
- resolves the script source and result variable from the compiled process,
- reads the instance's variables as the script's inputs,
- runs the script through exec (off the processor goroutine, after fsync), and
- returns the result as the process variable named by the result variable, which the job completion writes back into the instance so a downstream gateway can route on it.
Returning an error leaves the job pending, exactly as for any worker; the runner completes it only on success.
Types ¶
type CmdExec ¶
type CmdExec struct {
Lang Lang // language spec
Bin string // interpreter override; empty means Lang.Bin
Timeout time.Duration // per-script wall-clock limit; <= 0 means defaultTimeout
// MaxOutput bounds what one script may write to stdout, in bytes; <= 0 means
// defaultMaxOutput. The server sets it from the installation's budgets.
MaxOutput int64
// contains filtered or unexported fields
}
CmdExec runs script tasks by shelling out to a real interpreter for its Lang. It is the production Exec; tests use a fake instead so they need no interpreter.
Security posture (ADR-0047): the interpreter runs with -NoProfile / -NonInteractive (or the language equivalent), the instance's variables and the source arrive as environment values (not interpolated), each run is bounded by Timeout (the process is killed at the deadline), and it runs in the worker's trust domain — never with the engine's credentials. The eventual isolation boundary is an external worker in the customer's environment.
func (*CmdExec) Check ¶
Check reports whether the interpreter is resolvable on PATH. The server calls it once at startup so an operator whose host lacks the interpreter sees a clear warning, rather than watching script tasks park silently.
func (*CmdExec) Run ¶
Run passes the source and the variables to the interpreter's bootstrap via the environment, runs it under a deadline, and decodes its stdout as the result. A non-zero exit or a runner error leaves the job pending; an empty stdout decodes to a null result; overrunning the timeout kills the process and errors.
type Exec ¶
Exec runs a script off the hot path and returns its result. It is the seam between the worker and the real interpreter: CmdExec shells out to the language's interpreter, but tests inject a deterministic fake so they need no interpreter installed. input is the instance's variables keyed by name; the returned value is the script's result, a JSON-shaped Go value (nil, bool, json.Number, string, []any, or map[string]any) that becomes the result variable.
type Job ¶ added in v0.3.0
type Job struct {
Source string `json:"source"`
// Input is the scope chain flattened for the script, nearest scope winning
// (ADR-0068) — resolved by the engine, which is the only one that can walk it.
Input map[string]any `json:"input,omitempty"`
// Result names the process variable the script's output is written to; empty
// means the task writes nothing back.
Result string `json:"resultVariable,omitempty"`
}
Job is a script task with everything already looked up: the source to run and the variables it sees. It is what travels with a leased job.
func Resolve ¶ added in v0.3.0
func Resolve(store state.Reader, cp *compiler.CompiledProcess, detail *compiler.ScriptJobTaskDetail, elementInstanceKey uint64) (Job, error)
Resolve turns a compiled script task into a Job. Engine work by necessity: the source lives in the compiled process and the variables are reached by walking the element instance's scope chain in the store.
type Lang ¶
type Lang struct {
Name string // model/UI name, e.g. "python"
JobType int32 // reserved job-type index (compiler.*JobTypeIndex)
Bin string // default interpreter binary
Args func(bootstrap string) []string
Wrap string // the bootstrap program
}
Lang describes how to run one scripting language: the reserved job type its worker subscribes to, the default interpreter binary, the interpreter arguments that run a bootstrap program, and that bootstrap. The bootstrap is a fixed program (never the author's source) that reads the source and variables from the environment, exposes the variables, runs the source, and prints the result as JSON on stdout (empty output = null). Each language keeps its own idiomatic result convention (see the bootstraps).
func LangByName ¶
LangByName returns the language spec for a (lower-cased) language name, and whether it is one of the supported languages.
type ProcessLookup ¶
type ProcessLookup func(defKey uint64) *compiler.CompiledProcess
ProcessLookup resolves a process-definition key to its compiled process. The worker uses it to find the script source and result variable a job belongs to, so one handler serves every deployed process.
type Result ¶ added in v0.3.0
Result is what running a Job produces.