2.8 KiB
lifecycle
(no submodules)
Purpose
This module owns the idempotency wrapper around a VmSandboxHandle's
start / dispose lifecycle. The host's lifecycle driver may invoke
these hooks multiple times (e.g. a hot-reload's stop+start pair, or a
test harness's deterministic shutdown sequence); the wrapper makes the
double-invocation case a silent no-op rather than a throw, and
reflects under-the-hood sandbox throws via the bridge's
LIFECYCLE_FAILED code so the host's error boundary sees a uniform
shape.
Splitting the wrapper into its own module keeps the bridge factory small (no inline state machine) and gives the conformance harness a direct seam for asserting idempotency without standing up the full bridge.
Features
- Idempotent
start— second call returns without re-invokingsandbox.start(). - Idempotent
dispose— second call returns without re-invokingsandbox.dispose(). - Forbidden start-after-dispose — calling
start()afterdispose()raisesLIFECYCLE_FAILEDso the host can fail the hot-reload cleanly rather than silently swallowing the request. - Error wrapping — underlying sandbox throws surface as
SandboxVmBridgeErrorwithcode: LIFECYCLE_FAILEDand the original error preserved ascause. - Inspection helpers —
hasStarted()andisDisposed()for the bridge's internal request-pipeline guard.
Usage: Basic
import { createSandboxLifecycleForwarder } from "@suaveplan/api-sandbox-vm-host-bridge/lifecycle/lifecycle";
const forwarder = createSandboxLifecycleForwarder(sandbox);
await forwarder.start();
forwarder.dispose();
forwarder.dispose(); // no-op
Usage: Advanced
import { createSandboxLifecycleForwarder } from "@suaveplan/api-sandbox-vm-host-bridge/lifecycle/lifecycle";
const forwarder = createSandboxLifecycleForwarder(sandbox);
try {
await forwarder.start();
} catch (err) {
// err.code === "SAND_VM_BRIDGE.LIFECYCLE_FAILED"
// err.cause is the original SandboxVmError
rollbackJournal.markFailed(err);
}
API Reference
interface SandboxLifecycleForwarder—start(),dispose(),hasStarted(),isDisposed().createSandboxLifecycleForwarder(sandbox: VmSandboxHandle): SandboxLifecycleForwarder— factory; returns a frozen object.
Implementation Notes
The internal started / disposed flags are kept in a closure rather
than on the returned object so the sandbox cannot mutate them via a
property-set on the forwarder. The forwarder itself is Object.freezed
so consumers cannot patch dispose to skip the cleanup. Errors raised
inside dispose() are caught and rewrapped — the alternative (letting
them propagate raw) would mean the host's error boundary sees a mixed
shape (sometimes SandboxVmError, sometimes
SandboxVmBridgeError); the wrap keeps the boundary's branch arm
tight.