Decision records

ADR-0004: Two-level runtime contract (Handler / RuntimeAdapter)

  • Status: Accepted (2026-10-05)

Context

Handoff §5: core routing must not care whether the destination is PHP, Python, Node, a container, a Unix socket or a TCP service. Language specifics must not leak into the core.

Decision

  • scalws_core::Handler — request-path trait, object safe, returns a boxed future. The router stores Arc<dyn Handler> only.
  • scalws_runtime::RuntimeAdapter — lifecycle factory per runtime kind: validates a spec, prepares a RuntimeInstance.
  • scalws_runtime::RuntimeInstance — owns any processes/sockets, exposes LifecycleState, start, drain, and a Handler.
  • Managed runtimes talk to the server over Unix sockets (preferred) or loopback TCP. Their handler is a FastCGI (PHP) or HTTP proxy (Node, Python ASGI/WSGI servers) handler.

Consequences

  • PHP/Node/Python adapters are separate crates; the server registers them in a registry.
  • M1 handlers (static, proxy, respond) need no lifecycle and implement Handler directly; M2 wraps them as adapters so every runtime type goes through one registry.