phasync
Swerve / Manual

Swerve

Manual

The manual is a set of topic books. Each has an introduction, concepts, guides, examples and the reference for the classes and functions that belong to it.

Request handlers#

What the application returns, and how a request meets it.

  • Introduction
  • After the response – Keep working after the response is sent: send 10,000 e-mails without the client waiting.
  • Examples – Every example in this topic, with its output.
  • ClientRequest – One HTTP exchange with a client: the request to read, and the response to write. The application's RequestHandler is called once for each, and may keep it for as long as it likes (an event stream, a long download) by simply not returning.
  • HeadersSentException – The final response head was already committed: its status and headers can't change.
  • FormBody – The form data of a request, parsed when first asked for: what PHP puts in $_POST and $_FILES.
  • RequestBody – A request's body as a PSR-7 stream, read from the ClientRequest as the application reads it.
  • RequestHandler – What an application's swerve.php returns: the callable that serves each HTTP exchange.
  • ServerInterface – A protocol server, such as HTTP/1.1 (--http).
  • StaticFiles – Serves the files of a directory, and passes every other request on to the application's handler.
  • Swerve – What swerve gives the application: its log, the cache and the messages shared by every worker, and the state of the worker.

Long-lived connections#

Connections that stay open without holding a pooled resource.

WebSockets and SSE#

Push to the browser with Server-Sent Events or WebSockets.

  • Introduction
  • Realtime: SSE and WebSockets – Push to the browser with Server-Sent Events or WebSockets, across all workers.
  • Examples – Every example in this topic, with its output.
  • ServerSentEvents – A Server-Sent Events stream (EventSource in the browser) on a ClientRequest.
  • WebSocket – A WebSocket connection (RFC 6455), server side, on a ClientRequest or any Duplex.
  • WebSocketHandshake – The decision of WebSocket::handshake: the answer to a WebSocket handshake.

Coordination across workers#

Publish, subscribe and claim: requests that coordinate across worker processes.

  • Introduction
  • OrderedChannel – One order for every subscriber, from many publishers.
  • Claims – One holder at a time across all workers.
  • Examples – Every example in this topic, with its output.
  • Claim – A handle on a name that one holder at a time can hold across the whole server, from Swerve::claim.
  • OrderedChannel – A topic where every subscriber, in every worker, receives the messages in one and the same order, and each publisher's own messages keep theirs.
  • SubscriberLagException – A subscription fell further behind its topic than its $maxLag seconds, see Subscription.
  • Subscription – The messages published to a topic, from Swerve::subscribe: iterate over it to receive them.
  • Swerve::publish – Send a message to every subscriber of $topic, in every worker process of this swerve, this one included.
  • Swerve::publishRaw – Send $bytes unchanged to every subscriber of $topic, in every worker process of this swerve, this one included.
  • Swerve::subscribe – Receive what is published to $topic from now on.
  • Swerve::claim – A handle on the name $name, which one holder at a time can hold across the workers.
  • SealedObject – A decoded JSON object that nobody can change: what a subscriber of Swerve::subscribe gets for a published object.

Resource management#

A few database connections, and one cache, shared among thousands of requests.

  • Introduction
  • Caching: whose data is it? – A shared cache is safe when its key holds every input the value depends on.
  • Connections, pools and limits – A worker needs few database connections. Borrow one for a query or a transaction and give it back.
  • Cache – Swerve::cache(): one PSR-16 cache for every worker, read from memory in the worker.
  • Examples – Every example in this topic, with its output.
  • Cache – The cache every worker shares, from Swerve::cache(): a PSR-16 cache held by the master process, the least recently used entries evicted past --cache-size.
  • CacheKeyException – A key Swerve::cache can't take: PSR-16 keys are non-empty strings without {}()/@:.
  • Swerve::cache – The cache every worker shares, held by the master process.

Context switching#

What belongs to one request and what belongs to the worker.

Without the extension#

Write sequential PHP that stays concurrent.

Frameworks#

One adapter per framework; your application runs unchanged.

  • Introduction
  • Designing a framework for concurrent requests – A boot phase that ends, a container that closes, a scope per request, and reset hooks only as a last resort.
  • Case study: Laravel – What Laravel keeps in shared state, how the Swerve adapter handles it, and what the same state needs from your code.
  • Laravel: the container and facades – Registrations and fakes made during a request stay on shared objects. Register at boot; fake in tests.
  • Laravel: views, translator, router and paginator – Shared view data, translator lines and library pointers: set them at boot, pass the rest with the call.
  • Laravel: toggles, macros and process settings – Gate and macro registrations, static switches like Carbon::setTestNow(), and the settings PHP keeps per process.
  • Laravel: static caches – Which of Laravel's own static caches are memoization, whether they are bounded, and what flushes them.
  • Laravel – Run a Laravel application on Swerve: many requests at once, each in a pooled application of its own.
  • Symfony – Run a Symfony application on Swerve: one kernel per in-flight request, booted once and kept warm.
  • CodeIgniter – Run a CodeIgniter 4 application on Swerve through its own worker mode, one request at a time per worker.
  • CakePHP – Run a CakePHP 5 application on Swerve: booted once per worker, one request at a time, like PHP-FPM.
  • Yii – Run a Yii 3 application on Swerve, one request at a time per worker.
  • Laminas – Run a Laminas MVC or Mezzio application on Swerve. MVC rebuilds the application per request and serializes it; Mezzio runs concurrently.
  • PSR-15 – Run Slim, Mezzio or your own PSR-15 handler on Swerve with the swerve-psr15 adapter: one boot per worker, requests overlap.

Production#

Sizing, reloads, logging and shutdown.

  • Introduction
  • Production – Sizing, reloads, logging, limits and the phasync extension.
  • Examples – Every example in this topic, with its output.
  • StopReason – Why a worker stops, see WorkerStoppingException.
  • Swerve::log – The log of this process: swerve's own PSR-3 logger, in its format (the time, this worker's slot).
  • Swerve::setLog – Replace the logger that Swerve::log returns.
  • Swerve::draining – Whether this worker drains: it is shutting down, reloading or being recycled.
  • Swerve::onShutdown – Run $callback when this worker must now close its connections: for an upgraded connection, to say goodbye in its protocol and end it.
  • Swerve::awaitShutdown – Wait until this worker must close its connections, see Swerve::onShutdown.
  • Swerve::ini – php.ini settings a package needs in every swerve process. Call it from a file listed in your package's composer.json files: Composer loads it after swerve's own, as the master starts. swerve applies the settings with its startup restart, over its own settings; an explicit -d on the command line still wins.
  • Swerve::onWorkerStart – Run $callback in every worker as it starts, before the application loads, inside the worker's event loop, so it may start coroutines that run for the worker's life. Register it the way Swerve::ini says; calls after startup change nothing. A callback that throws stops the worker, as an application that fails to load does.
  • Swerve::getVersion – The installed version, as Composer knows it: 0.1.0, or dev-main in a checkout.
  • WorkerStoppingException – Thrown into the coroutines still running when a worker stops, once its requests have finished (or its drain time is over): clean up at once, then let it end; the worker exits shortly after, whether or not they have. A phasync ShutdownException, so a CancelledException: code that only needs to stop catches nothing. $reason says why, for telling a client what happens next.