@molecule/api-deploy-rollout-sandbox

Provider bond · deploy-rollout · API (Node) · v1.1.1 · Apache-2.0

Sandbox provider bond for @molecule/api-deploy-rollout: grow-then-shrink rolling deploys over any @molecule/api-code-sandbox provider (E2B, Docker, Fly).

npm install @molecule/api-deploy-rollout-sandbox

npm · Source on GitHub · Implements @molecule/api-deploy-rollout

How it works

@molecule/api-deploy-rollout-sandbox is a provider bond on the API (Node) side: it implements the deploy-rollout core interface (@molecule/api-deploy-rollout) with a concrete vendor or library behind it.

Your code calls the core; you wire this provider once at startup. Swapping vendors later is one line in that wiring, not a rewrite.

import { runRollout, setProvider } from '@molecule/api-deploy-rollout'
import { provider } from '@molecule/api-deploy-rollout-default'
import { createSandboxInstanceProvider } from '@molecule/api-deploy-rollout-sandbox'

setProvider(provider)
await runRollout({
  provider: createSandboxInstanceProvider({
    provider: sandboxProvider,
    launch: (index) => launchReplica(index),
    join: (instance) => upsertUpstream(instance.upstreamUrl ?? ''),
  }),
  current: oldInstances,
  policy: { replicas: 2 },
})

Works with: @molecule/api-code-sandbox, @molecule/api-deploy-rollout

Reference

Sandbox provider bond for the deploy-rollout core.

One adapter over @molecule/api-code-sandbox, so E2B, Docker and Fly sandboxes share one rolling-deploy implementation. The deploy supplies its launch recipe and readiness gate; the bond supplies the lifecycle.

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Quick Start

import { runRollout, setProvider } from '@molecule/api-deploy-rollout'
import { provider } from '@molecule/api-deploy-rollout-default'
import { createSandboxInstanceProvider } from '@molecule/api-deploy-rollout-sandbox'

setProvider(provider)
await runRollout({
  provider: createSandboxInstanceProvider({
    provider: sandboxProvider,
    launch: (index) => launchReplica(index),
    join: (instance) => upsertUpstream(instance.upstreamUrl ?? ''),
  }),
  current: oldInstances,
  policy: { replicas: 2 },
})

Type

provider

Installation

npm install @molecule/api-deploy-rollout-sandbox @molecule/api-code-sandbox @molecule/api-deploy-rollout

API

Interfaces

SandboxInstance

One sandbox instance plus the address the edge dials.

interface SandboxInstance extends RolloutInstance {
  /** The live sandbox handle, when this run holds it. */
  sandbox: Sandbox | null
}

SandboxInstanceOptions

How a sandbox rollout reaches and gates one app's instances.

interface SandboxInstanceOptions {
  /** The sandbox provider (E2B, Docker, Fly — any bonded provider). */
  provider: SandboxProvider

  /**
   * Create and start the instance at `index`, resolving once it exists. This is the
   * deploy's own recipe (tree transfer, env, boot script); the bond never guesses
   * it.
   */
  launch: (index: number) => Promise<{ sandbox: Sandbox; upstreamUrl: string }>

  /**
   * A BLOCKING readiness gate with the caller's own semantics and budget. When
   * present, `waitReady` delegates to it. When absent, the bond polls
   * `readinessProbe` until `readinessTimeoutMs` elapses.
   */
  waitReady?: (instance: SandboxInstance) => Promise<boolean>

  /**
   * One HTTP readiness probe. Default: `GET <upstreamUrl>/health/ready`, falling
   * back to `GET <upstreamUrl>/health` on 404/405 (an app scaffolded before the
   * lifecycle bond answers only the latter).
   */
  readinessProbe?: (instance: SandboxInstance) => Promise<boolean>

  /** How long the bond's own readiness poll may take. Defaults to 120 s. */
  readinessTimeoutMs?: number

  /** Probe cadence for the bond's own readiness poll. Defaults to 2000 ms. */
  readinessPollMs?: number

  /**
   * The shell command that tells the app to drain. Defaults to a SIGTERM to the
   * sandbox's node processes (`sigtermNodeProcessesCommand`).
   */
  drainCommand?: string | ((drainMs: number) => string)

  /** Add a ready instance to the caller's routable set. Default: no-op. */
  join?: (instance: SandboxInstance) => Promise<void>

  /** Remove an instance from the caller's routable set. Default: no-op. */
  leave?: (instance: SandboxInstance) => Promise<void>

  /**
   * Enumerate this deployment's live instances, when the caller can. Used by the
   * rollout's idempotent resume; omitted means "roll from the caller's set".
   */
  list?: () => Promise<SandboxInstance[]>
}

Functions

sigtermNodeProcessesCommand(drainMs)

A drain command that sends SIGTERM to the sandbox's node processes and waits, bounded, for them to exit.

The lifecycle bond turns SIGTERM into "flip readiness to 503, finish in-flight requests, exit". An app without the bond ignores the signal and the rollout destroys it after the same bound — no worse than destroying it without a word.

function sigtermNodeProcessesCommand(drainMs: number): string
  • drainMs — How long to wait for those processes to exit.

Returns: The shell command.

probeSandboxReadiness(instance, timeoutMs)

One HTTP readiness look at an instance.

/health/ready first; a 404 or 405 means the app predates the lifecycle bond, so /health is asked instead. Any other non-2xx answer is "not ready", and a transport failure is "not ready" too (the instance may still be booting).

function probeSandboxReadiness(instance: SandboxInstance, timeoutMs?: number): Promise<boolean>
  • instance — The instance to probe.
  • timeoutMs — Per-request budget. Defaults to 5000 ms.

Returns: Whether it answered ready.

createSandboxInstanceProvider(options)

Create a grow-then-shrink instance provider over a sandbox provider.

function createSandboxInstanceProvider(
  options: SandboxInstanceOptions,
): InstanceProvider<SandboxInstance>
  • options — The provider, the launch recipe and the gate.

Returns: An InstanceProvider over sandboxes.

Constants

DEFAULT_SANDBOX_READINESS_TIMEOUT_MS

The default poll cadence for the bond's own readiness wait.

const DEFAULT_SANDBOX_READINESS_TIMEOUT_MS: 120000

DEFAULT_SANDBOX_READINESS_POLL_MS

The default per-probe budget.

const DEFAULT_SANDBOX_READINESS_POLL_MS: 2000

Core Interface

Implements @molecule/api-deploy-rollout interface.

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-code-sandbox ^1.0.0
  • @molecule/api-deploy-rollout ^1.0.0

Runtime Dependencies

  • @molecule/api-code-sandbox

  • @molecule/api-deploy-rollout

  • The launch recipe stays the deploy's. Building, copying and booting an app inside a sandbox is app knowledge; this bond never guesses it.

  • Readiness falls back. /health/ready first, /health on 404/405, so an app scaffolded before the lifecycle bond still gates correctly.

  • Drain is a SIGTERM, bounded, through the sandbox's own exec channel.