Help us shape the future of Go! Take the 2026 Go Developer Survey

wasmhost

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package wasmhost runs Hatamoto plugins: Extism (wazero) modules built from standard Go (or any Extism PDK language) with a hard sandbox.

Every plugin gets, from its manifest: a cap on linear memory, a per-hook call timeout (always on: without it neither the timeout nor a cancelled request can stop a spinning guest; 250 ms for filters and 10 s for actions unless the manifest says otherwise; it starts once an instance is ready, waiting for a slot and starting a cold instance are bounded separately), an empty filesystem, no network, and a pool of instances with an admission cap. An instance that saw any error is thrown away, because a Go runtime that trapped is poisoned. Plugins load and unload without restarting; the registry is an immutable map behind an atomic pointer, so the request path takes no host-wide lock.

Index

Constants

This section is empty.

Variables

View Source
var ErrCircuitOpen = errors.New("wasmhost: plugin hook disabled after repeated failures")

ErrCircuitOpen is returned without running the guest while the circuit breaker for that plugin export is open.

View Source
var ErrNotLoaded = errors.New("wasmhost: plugin not loaded")

ErrNotLoaded is returned when calling a plugin that is not (or no longer) loaded.

View Source
var ErrOutputTooLarge = errors.New("wasmhost: plugin output too large")

ErrOutputTooLarge is returned when a call's output exceeds the plugin's max_output_bytes.

View Source
var ErrSaturated = errors.New("wasmhost: plugin saturated")

ErrSaturated wraps the context error of a call that gave up waiting for a free instance slot.

Functions

This section is empty.

Types

type Host

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

Host owns every loaded plugin.

func New

func New(log *slog.Logger, cacheDir string) (*Host, error)

New returns a Host. cacheDir != "" persists wazero's compiled code there so a restart does not recompile every module (about a second per Go guest); otherwise compiled code is cached in memory only. The directory is created private (0700): it holds native machine code the server executes. The cache is rebuildable, so a directory that cannot be used costs speed, not correctness: it is logged and the cache stays in memory.

func (*Host) Call

func (h *Host) Call(ctx context.Context, name, export string, in []byte) ([]byte, error)

Call runs export on plugin name with JSON input and returns its output.

A trap, timeout, out-of-memory or guest error returns an error and discards the instance that saw it; only a deliberate rejection (sdk.RejectPrefix) keeps its instance. Calls beyond the plugin's max_instances wait for a free slot until ctx ends or slotWait passes, then fail with ErrSaturated (the instances are untouched), so memory use stays inside max_instances x memory_pages x 2. The hook's timeout covers only the guest's run: neither the slot wait nor a cold start (at most maxStartWait) is charged to it, so the worst latency without a caller deadline is slotWait + maxStartWait + the hook's timeout. A caller deadline shortens all three together: the wait, the start and the run share it, so hooks called with one (render.head, jsonld.enrich) can still be cut short by it; that cut is not counted against the circuit breaker when our own waiting (slot wait plus cold start) was what shortened the guest's run; a guest cut by a short caller deadline that it had to itself is charged as usual.

func (*Host) Close

func (h *Host) Close(ctx context.Context)

Close unloads every plugin and the compilation cache.

func (*Host) Discarded

func (h *Host) Discarded(name string) int64

Discarded reports how many instances of name were dropped after failures (-1 when the plugin is not loaded).

func (*Host) HasExport

func (h *Host) HasExport(name, export string) bool

HasExport reports whether the plugin exports a function called export.

func (*Host) Load

func (h *Host) Load(ctx context.Context, m sdk.Manifest, wasm []byte) error

Load compiles wasm and places the plugin under m.Name, replacing a plugin of the same name once the old one's in-flight calls have finished. The manifest is validated and defaulted here; a module that cannot be compiled and instantiated fails the load. A Go guest's init() runs on the first call, not here, so a panicking init() fails every call instead.

func (*Host) Loaded

func (h *Host) Loaded() []string

Loaded reports the names currently loaded, sorted.

func (*Host) SetHostCall

func (h *Host) SetHostCall(fn HostCall)

SetHostCall sets who answers hm_call for plugins loaded from now on. Without it every call fails with an "unavailable" error response.

func (*Host) Unload

func (h *Host) Unload(ctx context.Context, name string) bool

Unload removes the plugin and frees its runtime once in-flight calls end.

type HostCall

type HostCall func(ctx context.Context, plugin string, in []byte) []byte

HostCall serves a plugin's hm_call import: in is the guest's request, the result goes back to it. ctx is the context of the hook call that is running the guest (its values and deadline), so the callee can bind itself to the call. The callee never fails: errors are encoded in the response.

Jump to

Keyboard shortcuts

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