Vanilla PHP & FrankenPHP Worker Mode
When running custom, framework-agnostic, or microservice applications with FrankenPHP Worker Mode, Leakless provides a wrapper helper: TheMattos\Leakless\Integrations\FrankenPhp\FrankenPhp.
The Worker Script
Create your worker entry point (e.g. worker.php):
php
<?php
declare(strict_types=1);
use TheMattos\Leakless\Config;
use TheMattos\Leakless\Integrations\FrankenPhp\FrankenPhp;
require_once __DIR__ . '/vendor/autoload.php';
// 1. Configure thresholds and safety policies
$config = new Config(
maxRssMb: 256.0,
maxRequests: 1000,
checkTransactions: true,
rollbackState: true,
logViolations: true,
);
// 2. Wrap your application handler in the FrankenPHP worker loop
FrankenPhp::run(function () {
// Application request logic
header('Content-Type: application/json');
echo json_encode([
'message' => 'Handled cleanly by persistent worker',
'worker_pid' => getmypid(),
'timestamp' => microtime(true),
]);
}, $config);How FrankenPhp::run() Works
Under the hood, FrankenPhp::run() orchestrates the persistent execution lifecycle:
- Worker Bootstrapping: Initializes the
Leaklessinstance with yourConfig. - FrankenPHP Native Polling: Uses
frankenphp_handle_request()to wait for incoming HTTP requests. - Automatic Lifecycle Wrapping:
- Calls
$leakless->startRequest()before your handler executes. - Executes your application handler inside a protected
try / finallyboundary. - Calls
$leakless->endRequest()in thefinallyblock to guarantee transaction auditing, state rollback, and RSS ceiling validation.
- Calls
- Graceful Worker Break: If the memory ceiling or max request limit is reached,
FrankenPhp::run()cleanly exits the loop, allowing the FrankenPHP process manager to spawn a new clean worker.
Custom Event Loops & Manual Usage
If you are writing a custom event loop or micro-framework, you can invoke the core Leakless lifecycle methods directly:
php
use TheMattos\Leakless\Leakless;
use TheMattos\Leakless\Config;
$leakless = new Leakless(new Config(maxRssMb: 256.0));
while ($request = $server->accept()) {
$leakless->startRequest();
try {
$response = $app->handle($request);
$server->send($response);
} finally {
$report = $leakless->endRequest();
if ($report->shouldRecycle) {
// Gracefully terminate loop
break;
}
}
}