Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Roadrunner Worker Laravel Package

spiral/roadrunner-worker

The common codebase for all RoadRunner binary workers—the high-performance PHP application server, load balancer, and process manager that replaces Nginx+FPM with PSR-7/PSR-17 compatible HTTP and HTTP/2 support.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install via Composer: composer require roadrunner/worker (as of v3.8.0, the package was renamed from spiral/roadrunner-worker; the old name was retired). Current patch release: v3.8.2
  • Requires PHP 8.2+ — confirm your runtime, Docker base image, and CI matrix before upgrading
  • Initialize a basic worker by extending Spiral\RoadRunner\Worker and implementing a request loop (the namespace is unchanged by the rename):
    use Spiral\RoadRunner\Worker;
    
    require __DIR__ . '/vendor/autoload.php';
    
    $worker = new Worker();
    while ($req = $worker->waitRequest()) {
        try {
            $payload = json_decode($req->getPayload(), true);
            $response = ['result' => 'Handled: ' . ($payload['action'] ?? 'unknown')];
            $worker->respond($response);
        } catch (\Throwable $e) {
            $worker->error((string)$e);
        }
    }
    
  • Configure .rr.yaml to point to your worker script (exec: php worker.php)
  • Start RoadRunner: ./rr serve
  • First use case: background jobs or long-running HTTP requests with persistent application state (queue consumers, HTTP microservices, Laravel Octane's RoadRunner driver)

Implementation Patterns

  • Migration from the old package name: replace spiral/roadrunner-worker with roadrunner/worker in composer.json, run composer update roadrunner/worker, and grep for the old name in docs, Dockerfiles, and CI caches. composer why spiral/roadrunner-worker quickly reveals transitive dependents (Laravel Octane, spiral/roadrunner-laravel, nyholm/psr7-server bridges) that may pin the legacy name.
  • Keep roadrunner/roadrunner installed alongside the worker: since v3.8.2, the worker detects the RoadRunner version through the roadrunner/roadrunner dependency rather than relying on a locally hardcoded constant. If your project prunes that package (e.g. composer remove --dev or a --no-dev build that drops it), version detection degrades. Leave it in require and let it resolve transitively via Octane / spiral/roadrunner-laravel.
  • Separate worker types: create dedicated workers for different job queues (QueueWorker, HttpWorker) by checking request headers (e.g., rr-worker-type) or payload structure
  • Dependency injection: boot your DI container outside the loop and reuse services inside it for performance:
    $container = buildContainer(); // expensive setup once
    while ($req = $worker->waitRequest()) {
        $handler = $container->get(SomeHandler::class);
        $handler->handle($req);
    }
    
  • Job dispatching: wrap payloads in PSR-7/18 style objects (e.g., Spiral\RoadRunner\PSR7Client) and pass to Symfony Messenger or Laravel Queue for unified processing
  • Graceful shutdown: use $worker->isStopRequested() in the loop to respond to RoadRunner's /stop signal and flush pending work before exiting
  • Metrics & logging: integrate with a PSR-3 logger; emit metrics via ext-ffi or ext-prometheus before respond() for observability
  • Version-aware startup checks: in your worker bootstrap, log the detected RoadRunner version once at boot (see the version-mismatch gotcha below) and fail fast if it's outside the range your code expects — cheaper than debugging a protocol error mid-request
  • Custom workers: since v3.8.0 core and extension classes consistently annotate overridden methods with #[\Override]. When you subclass Worker or related classes, add #[\Override] to the methods you override — PHP will now fail fast at class-load if a parent signature changes or a method is removed in a future release. This is a cheap upgrade safety net worth adopting in your own workers too.

Gotchas and Tips

  • Package rename (breaking): any composer require spiral/roadrunner-worker in docs or scripts must become roadrunner/worker. Old lock files will keep resolving the legacy name until you update; CI that installs from a stale composer.lock may silently stay on v3.7.x. Verify with composer show roadrunner/worker and composer show | grep roadrunner.
  • Version detection moved (v3.8.2): the RoadRunner version is now read from the roadrunner/roadrunner package instead of any hardcoded/duplicated constant. Practical impact:
    • If you were asserting on Spiral\RoadRunner\Version::VERSION in your own tests, that value now tracks the installed roadrunner/roadrunner release — pin it in composer.json if you need a deterministic assertion.
    • Custom Docker images that copy the rr binary in manually but skip roadrunner/roadrunner will report no/incorrect version. Either install the package or set RR_VERSION explicitly as an override.
    • Bump roadrunner/roadrunner and the rr binary together; a stale binary against a freshly resolved package is the most common source of phantom mismatches.
  • PHP 8.2 floor: v3.8.0 drops support for 8.0/8.1. If you're on Laravel 9/10 with PHP 8.1, stay on v3.7.x or upgrade PHP first — Composer will refuse the update otherwise.
  • Memory leaks: avoid storing request-specific data in static properties — they leak over time. Use instance variables inside the loop scope, or explicitly clear them per request
  • Uncaught exceptions: RoadRunner will terminate the worker if unhandled exceptions escape the loop. Always wrap processing in try/catch and use $worker->error($msg) for non-fatal issues
  • Payload format mismatches: RoadRunner may send Psr\Http\Message\ServerRequestInterface (via spiral/roadrunner-http) or raw strings (via spiral/roadrunner-queue). Decode appropriately using $req->getPayload() or cast to PSR if available
  • Debugging: enable RR_DEBUG=1 and check RoadRunner logs (./rr serve -d) to see worker communication. For version issues specifically, dump composer show roadrunner/roadrunner next to ./rr --version — the two must agree.
  • Extension points: leverage Spiral\RoadRunner\Environment to externalize config; override Worker methods like respond() for custom serialization (e.g., JSON to MessagePack) — and mark them #[\Override]
  • Version mismatch: roadrunner/worker v3+ requires RoadRunner v2. From v3.8.2 onward the worker derives the expected version from the installed roadrunner/roadrunner package, so keep package and binary in lockstep; use the RR_VERSION env var only as a manual override when the package isn't present. The v3.8.0 rename and this detection change do not alter the RoadRunner binary compatibility contract.
  • Patch-level upgrades are safe: 3.8.1 → 3.8.2 is a single bug fix with no API changes. composer update roadrunner/worker inside the 3.8.x line requires no code edits — just re-run your worker smoke test and confirm the logged version matches the binary.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console