wasm

package
v0.7.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 21, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Snapshot artifact layout and validation per plans/wasm-runtime.md §4.8.1.

Index

Constants

View Source
const DefaultWallTimeout = 5 * time.Minute

DefaultWallTimeout is the invocation budget when Capabilities.WallTimeoutNs is zero.

View Source
const ListenFDEnv = "AEROL_WASM_LISTEN_FD"

ListenFDEnv carries the wasip1 listener fd to AerolVM-aware guests. Guests that hardcode fd 3 (the bare-wasip1 convention) keep working when no dir preopens are configured; guests that also need /work read this env var to find the listener.

View Source
const WASIListenPortDisabled = -1

WASIListenPortDisabled means no wasip1 TCP listener is pre-opened (default).

Variables

View Source
var ErrEmptySnapshotDir = errors.New("snapshot directory missing")

ErrEmptySnapshotDir is returned when a checkpoint path is missing on disk.

View Source
var ErrNetworkEgressBlocked = errors.New("network egress blocked by quota")

ErrNetworkEgressBlocked is returned when quota policy blocks outbound dials.

Functions

func DirExists

func DirExists(dir string) bool

DirExists reports whether dir looks like a mem.snap artifact.

func EngineNameWasmtime

func EngineNameWasmtime() string

EngineNameWasmtime returns the §4.8.1 engine identifier for the optional wasmtime backend (UC-42b).

func EngineNameWazero

func EngineNameWazero() string

EngineNameWazero returns the §4.8.1 engine identifier for the default backend.

func FenceCloneGeneration

func FenceCloneGeneration(rowGen, snapshotGen string) error

FenceCloneGeneration rejects snapshots older than the store row token.

func ListenerFD

func ListenerFD(caps Capabilities) int

ListenerFD returns the fd wazero assigns the single wasip1 TCP listener: stdio (0–2), then len(preopens) dir fds, then the listener (InitFSContext order).

func MemoryLimitPages

func MemoryLimitPages(memoryMB int) uint32

MemoryLimitPages converts a MiB cap to WASM pages (64KiB each). Zero means no limit.

func ResolvedListenPort

func ResolvedListenPort(mod api.Module) (port int, ok bool)

ResolvedListenPort returns the host TCP port bound by a wasip1 pre-open listener.

func SnapshotMediaTypes

func SnapshotMediaTypes() map[string]string

SnapshotMediaTypes documents the v1 layer media types for AOCR push.

func WallTimeoutFromCaps

func WallTimeoutFromCaps(caps Capabilities) time.Duration

WallTimeoutFromCaps returns the wall-clock budget for one guest invocation.

func WithInvocationDeadline

func WithInvocationDeadline(ctx context.Context, caps Capabilities) (context.Context, context.CancelFunc)

WithInvocationDeadline wraps ctx with the caps wall timeout (epoch-style on wazero).

func WriteSnapshotDir

func WriteSnapshotDir(dst string, cap SnapshotCapture) error

WriteSnapshotDir atomically writes a mem.snap directory at dst.

Types

type ByteMeter

type ByteMeter interface {
	AddIn(n int64)
	AddOut(n int64)
}

ByteMeter accumulates sandbox network byte counters (UC-43).

type Capabilities

type Capabilities struct {
	Env           map[string]string `json:"env,omitempty"`
	Preopens      []Preopen         `json:"preopens,omitempty"`
	Args          []string          `json:"args,omitempty"`
	MemoryMB      int               `json:"memory_mb,omitempty"`
	WallTimeoutNs int64             `json:"wall_timeout_ns,omitempty"`
	// WASIListenPort enables wasip1 pre-open TCP listeners when >= 0 (0 = ephemeral).
	// When unset, use -1 to disable.
	WASIListenPort int    `json:"wasi_listen_port,omitempty"`
	WASIListenHost string `json:"wasi_listen_host,omitempty"`
}

Capabilities configures WASI preopens, env, args, and resource limits for an instance.

func CapsFromResourceLimits

func CapsFromResourceLimits(base Capabilities, memoryMB int, wallTimeout time.Duration) Capabilities

CapsFromResourceLimits projects host limits into engine capabilities.

func (Capabilities) ListenEnabled

func (c Capabilities) ListenEnabled() bool

ListenEnabled reports whether wasip1 pre-open TCP listeners are active.

type Engine

type Engine interface {
	// LoadModule compiles bytes from path. Idempotent per path within one engine.
	LoadModule(ctx context.Context, path string, opts LoadOptions) error
	// Instantiate creates a runnable instance with the given capabilities.
	Instantiate(ctx context.Context, caps Capabilities) error
	// InvokeExport calls an exported function by name.
	InvokeExport(ctx context.Context, name string) error
	// Run re-instantiates with caps, invokes export, and captures stdout/stderr.
	Run(ctx context.Context, caps Capabilities, export string) (RunResult, error)
	// StopInstance tears down the active instance but keeps the compiled module.
	StopInstance(ctx context.Context) error
	// CaptureSnapshot exports linear memory from the active instance.
	CaptureSnapshot(ctx context.Context) (SnapshotCapture, error)
	// RestoreSnapshot re-instantiates and loads memory from a capture.
	RestoreSnapshot(ctx context.Context, snap SnapshotRestoreInput, caps Capabilities) error
	// Close releases compiled module and any active instance.
	Close(ctx context.Context) error
	// ResolvedListenPort returns the host port for an ephemeral wasip1 listener (0 in caps).
	ResolvedListenPort() (int, bool)
	// SupportsListen reports whether the engine can host a wasip1 TCP listener
	// (the HTTP ingress / expose_port path). wazero can; the wasmtime backend
	// cannot yet (see plans/wasm-runtime.md "Still open"). Callers must reject
	// listen requests up front rather than silently failing to resolve a port.
	SupportsListen() bool
}

Engine compiles and runs a single WASM module with WASI.

func NewEngine

func NewEngine(ctx context.Context) (Engine, error)

NewEngine constructs the default wazero-backed engine.

func NewEngineFor

func NewEngineFor(ctx context.Context, name string) (Engine, error)

NewEngineFor constructs an engine by name. Empty name selects wazero.

type LoadOptions

type LoadOptions struct {
	MemoryMB int
}

LoadOptions carries per-load engine configuration. MemoryMB sets the wazero runtime memory-limit pages before compilation so a later Instantiate with the same cap does not rebuild the runtime (plans/wasm-create-latency.md Phase 1).

type LoadTimingReporter

type LoadTimingReporter interface {
	LastLoadTimings() LoadTimings
}

LoadTimingReporter is an optional engine capability: an engine that implements it exposes the sub-stage breakdown of its most recent LoadModule. It is type-asserted by the worker (like NetworkAwareEngine) so the base Engine interface — and the wasmtime backend and the test mocks that implement it — stay untouched.

type LoadTimings

type LoadTimings struct {
	NewEngine   time.Duration `json:"new_engine_ns,omitempty"`
	RuntimeInit time.Duration `json:"runtime_init_ns,omitempty"`
	Read        time.Duration `json:"read_ns,omitempty"`
	Compile     time.Duration `json:"compile_ns,omitempty"`
}

LoadTimings breaks the cold-create wasm_load stage into its sub-costs. It exists because a single wasm_load timer told us the stage was ~2.8s p50 for CPython on t3.medium but not WHICH step owned it — and the firecracker create-latency episode proved that guessing the dominant sub-cost before measuring it burns effort on the wrong lever. Splitting the timer lets the create path emit per-step Server-Timing entries so the resident-module work (plans/wasm-resident-module-host.md) targets the real bottleneck.

The fields mirror the cold LoadModule sequence in the worker:

NewEngine   — worker: NewEngineFor builds the first wazero runtime + WASI.
RuntimeInit — engine: LoadModule rebuilds the runtime at the target memory
              limit (+ WASI + compile-cache open). This is a second runtime
              build today; see the plan's "redundant double init" note.
Read        — engine: os.ReadFile of the module bytes (25MB for CPython).
Compile     — engine: wazero CompileModule (compile-cache assisted; a full
              cold compile is ~10s, a cache hit ~seconds of deserialize).

Durations marshal to JSON as their nanosecond integer (time.Duration is int64), so they cross the worker IPC boundary losslessly.

type MultiInstanceEngine

type MultiInstanceEngine struct {
	// contains filtered or unexported fields
}

MultiInstanceEngine holds one resident wazero runtime + one compiled module and instantiates many isolated instances from it — compile-once, instantiate-many. It is the Phase 1 primitive for the resident-module host (plans/wasm-resident-module-host.md), extended in Phase 2b PR-A with per-instance network hooks (multiNetHost) and call/lifecycle locking.

Bucketing constraint: wazero sets the memory limit at the runtime level and a CompiledModule is bound to its runtime, so one MultiInstanceEngine serves a single (module, memoryMB) bucket. MemoryMB is fixed at construction.

Isolation: wazero gives every InstantiateModule its own linear memory. Networking is keyed by mod.Name() (= sandboxID) via multiNetHost so co-tenants cannot share sockets. wasip1 listeners and checkpoint/restore remain out of scope for resident hosts.

func NewMultiInstanceEngine

func NewMultiInstanceEngine(ctx context.Context, memoryMB int) (*MultiInstanceEngine, error)

NewMultiInstanceEngine builds the resident runtime (memory-limited to memoryMB, sharing the on-disk compile cache + base wasip1 host) with no module compiled yet. Call LoadModule once, then Instantiate per sandbox.

func (*MultiInstanceEngine) ClearNetworkHook

func (m *MultiInstanceEngine) ClearNetworkHook(sandboxID string)

ClearNetworkHook drops the sandbox's hook and closes every conn it owns.

func (*MultiInstanceEngine) Close

func (m *MultiInstanceEngine) Close(ctx context.Context) error

Close tears down every instance, the compiled module, and the runtime.

func (*MultiInstanceEngine) HasInstance

func (m *MultiInstanceEngine) HasInstance(sandboxID string) bool

HasInstance reports whether sandboxID has a live instance.

func (*MultiInstanceEngine) InstanceCount

func (m *MultiInstanceEngine) InstanceCount() int

InstanceCount is the number of live instances (for pool accounting + tests).

func (*MultiInstanceEngine) Instantiate

func (m *MultiInstanceEngine) Instantiate(ctx context.Context, sandboxID string, caps Capabilities) error

Instantiate creates an isolated instance keyed by sandboxID from the resident compiled module. This is the fast path the whole design exists for: it costs an Instantiate (~9ms), not a CompileModule (~2.8s). _start is NOT run here (deferred, matching the single-instance engine); callers invoke it explicitly.

func (*MultiInstanceEngine) InvokeExport

func (m *MultiInstanceEngine) InvokeExport(ctx context.Context, sandboxID, name string) error

InvokeExport calls an exported function on one instance. The engine lock is released before the call so a long-running export does not serialize co-tenants; the per-instance lock keeps StopInstance from Closing underfoot.

func (*MultiInstanceEngine) LastLoadTimings

func (m *MultiInstanceEngine) LastLoadTimings() LoadTimings

LastLoadTimings satisfies LoadTimingReporter. NewEngine/RuntimeInit are left zero — this engine builds its runtime once at construction, not per load.

func (*MultiInstanceEngine) LoadModule

func (m *MultiInstanceEngine) LoadModule(ctx context.Context, path string) error

LoadModule compiles the module at path once; every later Instantiate reuses the resident CompiledModule. A repeat call recompiles (e.g. module upgrade) and closes the previous compiled module — existing live instances keep running on their own already-instantiated code.

func (*MultiInstanceEngine) Loaded

func (m *MultiInstanceEngine) Loaded() bool

Loaded reports whether a module has been compiled into the resident runtime.

func (*MultiInstanceEngine) MemoryMB

func (m *MultiInstanceEngine) MemoryMB() int

MemoryMB is the fixed memory limit (MB) this engine's runtime + compiled module are built for. The pool routes only matching-memory creates here.

func (*MultiInstanceEngine) Run

func (m *MultiInstanceEngine) Run(ctx context.Context, sandboxID string, caps Capabilities, export string) (RunResult, error)

Run (re-)instantiates the sandbox's instance with stdout/stderr capture and invokes export (default _start), returning the captured output — the one-shot Exec path for a resident-hosted sandbox. It mirrors the single-instance engine's Run (re-instantiate per call so a fresh Exec starts clean), but keyed by sandboxID and reusing the resident compiled module, so it costs an Instantiate (~9ms), not a compile. A non-zero guest exit is returned in the RunResult (not as a Go error), matching the single-instance engine.

func (*MultiInstanceEngine) SetNetworkHook

func (m *MultiInstanceEngine) SetNetworkHook(sandboxID string, hook *NetworkHook)

SetNetworkHook binds a per-sandbox NetworkHook for mediated egress. The hook is looked up at host-fn call time by mod.Name() (= sandboxID).

func (*MultiInstanceEngine) StopInstance

func (m *MultiInstanceEngine) StopInstance(ctx context.Context, sandboxID string) error

StopInstance closes one instance and leaves every co-tenant running. Idempotent: stopping an unknown sandboxID is a no-op. Waits for in-flight InvokeExport/Run calls on that instance, then closes owned network conns.

type NetByteCounter

type NetByteCounter struct {
	// contains filtered or unexported fields
}

NetByteCounter is a thread-safe ByteMeter backed by atomic counters.

func (*NetByteCounter) AddIn

func (c *NetByteCounter) AddIn(n int64)

func (*NetByteCounter) AddOut

func (c *NetByteCounter) AddOut(n int64)

func (*NetByteCounter) In

func (c *NetByteCounter) In() int64

func (*NetByteCounter) Out

func (c *NetByteCounter) Out() int64

type NetDialer

type NetDialer interface {
	DialContext(ctx context.Context, network, address string) (net.Conn, error)
}

NetDialer dials outbound TCP for a sandbox. Implementations must enforce egress policy and byte accounting (UC-43 NetMediator in the worker).

type NetworkAwareEngine

type NetworkAwareEngine interface {
	Engine
	SetNetworkHook(hook *NetworkHook)
	ClearNetworkHook()
}

NetworkAwareEngine exposes per-sandbox network mediation on the default engine.

type NetworkHook

type NetworkHook struct {
	SandboxID string
	Dial      NetDialer
	// Meter receives wasip1 sock_accept/recv/send and host-module socket bytes.
	Meter ByteMeter
}

NetworkHook binds a sandbox identity to mediated egress dials for the engine.

type Preopen

type Preopen struct {
	GuestPath string `json:"guest_path"`
	HostPath  string `json:"host_path"`
}

Preopen maps a host directory into the guest filesystem.

type RunResult

type RunResult struct {
	ExitCode int        `json:"exit_code"`
	Stdout   string     `json:"stdout,omitempty"`
	Stderr   string     `json:"stderr,omitempty"`
	Usage    UsageStats `json:"usage,omitempty"`
}

RunResult captures a single invocation's outcome.

type SnapshotBaseModule

type SnapshotBaseModule struct {
	Digest string `json:"digest"`
	Size   int64  `json:"size"`
}

SnapshotBaseModule references the compiled module by digest.

type SnapshotCapture

type SnapshotCapture struct {
	Config    SnapshotConfig
	Memory    []byte
	Globals   []byte
	WASIState []byte
}

SnapshotCapture holds the host-boundary state written into mem.snap.

type SnapshotConfig

type SnapshotConfig struct {
	SchemaVersion     int                `json:"schema_version"`
	Engine            string             `json:"engine"`
	EngineVersion     string             `json:"engine_version"`
	WASIVersion       string             `json:"wasi_version"`
	BaseModule        SnapshotBaseModule `json:"base_module"`
	Entrypoint        string             `json:"entrypoint"`
	Durability        string             `json:"durability"`
	CapturedAt        string             `json:"captured_at"`
	CloneGeneration   string             `json:"clone_generation"`
	MemoryChecksum    string             `json:"memory_checksum"`
	WASIStateChecksum string             `json:"wasi_state_checksum"`
	GlobalsCount      int                `json:"globals_count"`
}

SnapshotConfig is the v1 config descriptor (§4.8.1).

type SnapshotRestoreInput

type SnapshotRestoreInput struct {
	Config    SnapshotConfig
	Memory    []byte
	Globals   []byte
	WASIState []byte
}

SnapshotRestoreInput is validated artifact content for engine reconstruction.

func ReadSnapshotDir

func ReadSnapshotDir(dir string, runningEngine string) (SnapshotRestoreInput, error)

ReadSnapshotDir loads and validates a mem.snap directory.

type UsageStats

type UsageStats struct {
	WallDurationMs int64 `json:"wall_duration_ms"`
	// Instructions is populated only on the wasmtime engine seam (UC-42b).
	Instructions int64 `json:"instructions,omitempty"`
}

UsageStats captures per-invocation metering for billing (UC-42a on wazero).

Directories

Path Synopsis
Package worker implements the WASM worker-subprocess pool (plans/wasm-runtime.md §2.1).
Package worker implements the WASM worker-subprocess pool (plans/wasm-runtime.md §2.1).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL