fastware v0.6.0 /src.fastware.supervise
On this page

Process supervision for ``fastware dev``: pre-spawn gates, health-gated readiness, backend and Vite topology ordering, and graceful process-group teardown.

#src.fastware.supervise

#src.fastware.supervise

Process supervision for the fastware dev CLI.

Provides :class:DevProcess (a single supervised child in its own process group, with graceful-then-kill teardown) and the orchestration that turns a validated :class:~fastware.devconfig.DevConfig into a running dev environment:

  1. pre-spawn gates (must pass before anything spawns),
  2. ordered, health-gated aux services,
  3. the topology-ordered vite + backend pair with readiness probes,
  4. a supervise loop that, on any component death, tears the rest down in reverse

order and exits non-zero naming the dead component.

Daemon mode detaches the whole supervisor and registers it in the Phase 11 instance registry (entry name "<app-name>-dev"), which dev status and dev stop read.

#DevRunError

Base class for dev-run failures.

#PreSpawnGateError

A pre-spawn gate did not pass; nothing was spawned.

#ReadinessError

A component did not become ready within its timeout.

#PortCollisionError

A required port is already in use.

#SWModeConflictError

The resolved in-process app is configured with sw_mode='cache'.

#ComponentDied

A supervised component exited; the environment was torn down.

#_http_answers

python
def _http_answers(url: str, timeout: float) -> bool

True if url answers at the HTTP level (any status), else False.

#run_pre_spawn_gates

python
def run_pre_spawn_gates(cfg: DevConfig) -> None

Run every pre-spawn gate; raise :class:PreSpawnGateError on the first failure.

#DevProcess

A supervised child process running in its own process group.

#start

python
def start(self) -> None

#pid

python
def pid(self) -> int | None

#is_running

python
def is_running(self) -> bool

#returncode

python
def returncode(self) -> int | None

#forward_signal

python
def forward_signal(self, sig: int) -> None

Forward sig to the child's process group (if still running).

#stop

python
def stop(self, grace_s: float | None=None) -> None

Graceful-then-kill: SIGTERM the group, wait grace_s, then SIGKILL.

#teardown

python
def teardown(components: list[DevProcess], grace_s: float=GRACE_DEFAULT) -> None

Stop components in reverse start order.

#supervise_loop

python
def supervise_loop(started: list[DevProcess], stop_flag: dict, poll_s: float=0.2) -> DevProcess | None

Block until a component dies or stop_flag['flag'] is set.

Returns the first dead :class:DevProcess, or None when a stop was requested (clean shutdown). Does not tear anything down -- the caller owns teardown so ordering stays in one place.

#_serve_in_process

python
def _serve_in_process(app_path: str, host: str, port: int, vite_port: int) -> None

Subprocess entry point: import an app, wrap with ViteDevProxy, serve it.

#_start_ordered

python
def _start_ordered(cfg: DevConfig, grace_s: float, started: list[DevProcess]) -> None

Start vite + backend in the order dictated by topology, readying each.

#resolve_backend_sw_mode

python
def resolve_backend_sw_mode(cfg: DevConfig) -> str | None

Import the in-process app and return its resolved sw_mode (or None).

Only meaningful for the app backend form; returns None for cmd-form backends (whose sw_mode cannot be introspected without running them).

#check_sw_mode

python
def check_sw_mode(cfg: DevConfig) -> None

Hard-error if the resolved in-process app uses sw_mode='cache'.

cmd-form backends run as opaque subprocesses whose sw_mode cannot be introspected without executing them, so the guard cannot verify them. Rather than skip silently, emit a one-line stderr notice so the operator knows the guard did not run for this backend.

#dev_pid_path

python
def dev_pid_path(cfg: DevConfig, pid_dir: Path | str | None=None) -> Path

#list_dev_instances

python
def list_dev_instances(cfg: DevConfig, pid_dir: Path | str | None=None)

Return live registered dev instances (registry entries with the dev role).

#stop_dev_instances

python
def stop_dev_instances(cfg: DevConfig, pid_dir: Path | str | None=None, grace_s: float=GRACE_DEFAULT)

Terminate every registered dev instance gracefully-then-kill. Returns them.

#_spawn_daemon

python
def _spawn_daemon(cfg: DevConfig, pid_dir: Path | str | None) -> int

Spawn a detached fastware dev run --no-daemon and wait for it to register.

#run_dev

python
def run_dev(cfg: DevConfig, *, daemon: bool, grace_s: float=GRACE_DEFAULT, pid_dir: Path | str | None=None) -> int

Run the dev environment. Foreground blocks; daemon detaches and returns.

Always performs the sw_mode='cache' hard-error check up front.

Search