Commit graph

2 commits

Author SHA1 Message Date
1e4ced9a39 feat(appd): implement TerminateApp process signaling via abort channel
SessionRegistry now tracks a oneshot abort sender per active session:
- abort_senders: HashMap<u64, oneshot::Sender<()>> field added.
- register_abort(session_id): creates the channel, stores the sender,
  returns the receiver to the supervise task.
- terminate(): removes the session state AND drops the abort sender,
  closing the channel and triggering the receiver in supervise.

runtime::supervise() now accepts abort_rx: oneshot::Receiver<()>:
- After the READY signal is received, the process-wait loop uses
  tokio::select! on child.wait() vs abort_rx.
- On abort: logs intent, calls child.kill(), then sets state Stopped.
- On natural exit: logs exit status, sets state Stopped.

dispatch::LaunchApp: calls register_abort immediately after launch,
passes the receiver to the spawned supervise task.

Integration test updated to pass the abort receiver.
2026-03-11 09:37:09 +01:00
86d0011016 feat(appd): implement runtime supervisor with process spawning and READY signal
runtime.rs — process lifecycle manager:
- supervise(session_id, app_id, registry): spawns the weft-runtime child
  process identified by WEFT_RUNTIME_BIN env var. If unset, logs debug
  and returns immediately (no-op until runtime binary is available).
- Child process invoked as: <WEFT_RUNTIME_BIN> <app_id> <session_id>
  with stdout/stderr piped, stdin closed.
- wait_for_ready(): reads stdout line-by-line; returns Ok(()) on first
  line matching 'READY'; returns Err if stdout closes without it.
- 30-second READY_TIMEOUT via tokio::time::timeout; on expiry, kills
  the child and transitions session to Stopped.
- On success: sets session state to Running, broadcasts AppReady to all
  connected WebSocket clients via registry broadcast channel.
- drain_stderr(): async task that forwards child stderr lines to tracing
  at WARN level for observability.
- On process exit: sets session state to Stopped regardless of exit code.

main.rs — wiring:
- SessionRegistry now owns broadcast::Sender<Response>; Default creates
  the channel internally. Added set_state(), subscribe(), broadcast()
  methods. Removed standalone broadcast_tx from run(); WS handlers
  subscribe via registry.lock().await.subscribe().
- dispatch::LaunchApp spawns a tokio task calling runtime::supervise
  immediately after creating the session. supervise is a no-op when
  WEFT_RUNTIME_BIN is unset, so existing tests are unaffected.

Cargo.toml: added tokio 'process' and 'time' features.
2026-03-11 09:17:20 +01:00