API Reference
Mustard Executor
Last updated 2026-04-13
Mustard Executor
MustardExecutor is a Node-side queue-oriented API built on top of the existing
Mustard and Progress primitives.
It exists for hosts that need to manage many resumable guest executions without
manually orchestrating start(), Progress.dump(), Progress.load(), and
resume() for every job.
Scope
The executor layer:
- keeps guest/runtime semantics in Rust
- keeps capability implementations in the host
- treats progress snapshots plus any detached compiled-program bytes as durable queue state
- reuses the existing snapshot policy and validation model
It does not:
- serialize host functions or live host futures
- change the same-version-only snapshot contract
- provide hard kill semantics for in-process host work
Public API
class MustardExecutor<TInput extends Record<string, StructuredValue>, TResult extends StructuredValue> {
constructor(options: {
program: Mustard;
capabilities: Record<string, Capability>;
snapshotKey?: string | Buffer | Uint8Array;
store: MustardExecutorStore<TInput, TResult>;
limits?: RuntimeLimits;
});
enqueue(input: TInput, options?: { jobId?: string }): Promise<string>;
get(jobId: string): Promise<MustardJobRecord<TInput, TResult> | null>;
cancel(jobId: string): Promise<void>;
runWorker(options?: {
maxConcurrentJobs?: number;
signal?: AbortSignal;
drain?: boolean;
}): Promise<void>;
}
enqueue() accepts the exact inputs object that will later be passed into
program.start({ inputs, ... }).
Job States
queued: durable input exists, no worker is executing itrunning: a worker is actively starting or resuming guest executionwaiting: guest execution suspended on a host capability and durable progress existscompleted: job produced a final structured resultfailed: job terminated with a guest-safe error recordcancelled: host requested cancellation and the job terminated through the explicit cancellation path
Store Contract
The executor depends on a pluggable store. The store is the source of truth for durable state; worker-local memory is only transient cache.
interface MustardExecutorStore<TInput, TResult> {
enqueue(record: MustardJobRecord<TInput, TResult>): Promise<{
jobId: string;
inserted: boolean;
}>;
get(jobId: string): Promise<MustardJobRecord<TInput, TResult> | null>;
claimRunnable(limit: number, workerId: string, now: number): Promise<string[]>;
releaseClaim(jobId: string, workerId: string): Promise<void>;
update(jobId: string, patch: Partial<MustardJobRecord<TInput, TResult>>): Promise<void>;
saveProgress(jobId: string, progress: SerializedProgress): Promise<void>;
loadProgress(jobId: string): Promise<SerializedProgress | null>;
deleteProgress(jobId: string): Promise<void>;
requestCancel(jobId: string): Promise<'cancelled' | 'requested' | 'ignored'>;
consumeCancel(jobId: string): Promise<boolean>;
}
Required semantics:
enqueue()is idempotent byjobIdclaimRunnable()must not hand the same job to two workers at onceupdate()must fail closed on invalid state transitions- a
waitingjob must have matching durable progress - terminal jobs must not remain claimable
Worker Invariants
Workers must preserve these invariants:
- guest execution starts only from durable
inputor a validated storedProgressblob - capability handlers always come from the current host process, never from durable state
- every durable restore uses explicit
capabilities,limits, andsnapshotKey - current addon
SerializedProgressblobs must preserve detachedprogramandprogram_idfields exactly when present - stored progress must be bound to its owning
jobId; this implementation derives a per-job snapshot key from the configured executorsnapshotKeybefore everystart()andProgress.load(...) - progress is persisted before a job is marked
waiting - terminal state is persisted before worker-local state is discarded
- invalid snapshots, missing capabilities, and missing stored progress fail the job closed
Cancellation
Cancellation stays cooperative and honest:
queuedjobs can move directly tocancelledwaitingjobs cancel by resuming the stored progress throughProgress.cancel()- already-running host handlers are not hard-preempted in-process; the executor can only honor cancellation before or after the host handler returns
Initial Implementation
The first implementation in this repository includes:
MustardExecutorInMemoryMustardExecutorStore- bounded worker concurrency with
maxConcurrentJobs drainmode for tests and batch scripts- durable queued/running/waiting/completed/failed/cancelled state in the in-memory store
Future durable stores can extend the same public executor API without changing the guest runtime model.