Weave Code
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 Laravel Package

spiral/roadrunner

High-performance PHP application server and process manager written in Go. RoadRunner replaces Nginx+FPM with long-running workers and a plugin system, offering HTTP(S)/2/3, FastCGI, PSR-7/17 support, and per-project extensibility.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spiral/roadrunner-cli
    ./vendor/bin/rr get-binary
    

    Verify the binary exists in your project root.

  2. Configure .rr.yaml:

    version: '3'
    server:
      command: "php worker.php"
    http:
      address: "0.0.0.0:8080"
    
  3. Create a Worker (worker.php):

    <?php
    use Spiral\RoadRunner;
    use Nyholm\Psr7\Factory\Psr17Factory;
    
    $worker = RoadRunner\Worker::create();
    $psrFactory = new Psr17Factory();
    
    $httpWorker = new RoadRunner\Http\PSR7Worker($worker, $psrFactory, $psrFactory, $psrFactory);
    
    while ($req = $httpWorker->waitRequest()) {
        $httpWorker->respond(new \Nyholm\Psr7\Response(200, [], 'Hello RoadRunner!'));
    }
    
  4. Run:

    ./rr serve -c .rr.yaml
    

First Use Case: PSR-7 HTTP Server

Replace your Laravel index.php with the above worker pattern. RoadRunner handles routing via middleware/plugins, so integrate Laravel’s middleware stack into the PSR-7 worker.


Implementation Patterns

1. Middleware Integration

  • Laravel Middleware: Wrap Laravel’s middleware in PSR-15 middleware and inject them into the PSR7Worker:

    $middleware = new class implements Psr\Http\Server\MiddlewareInterface {
        public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
            // Laravel middleware logic
            return $handler->handle($request);
        }
    };
    $httpWorker = new RoadRunner\Http\PSR7Worker($worker, $psrFactory, $psrFactory, $psrFactory, [$middleware]);
    
  • RoadRunner Middleware: Use built-in middleware (e.g., gzip, headers) in .rr.yaml:

    http:
      middleware: ["gzip", "headers"]
    

2. Queue Workers

  • Job Consumers: Replace Laravel’s queue workers with RoadRunner’s job plugin:
    $jobWorker = new RoadRunner\Job\JobWorker($worker);
    while ($job = $jobWorker->wait()) {
        $job->perform(); // Laravel job logic
        $job->ack();
    }
    
  • Configure in .rr.yaml:
    jobs:
      pool:
        num_workers: 4
      queue: redis://127.0.0.1:6379
    

3. gRPC Services

  • Protocol Buffers: Define .proto files and generate PHP classes. Use RoadRunner’s gRPC plugin:
    grpc:
      proto: "app/proto/*.proto"
    
  • Worker Integration:
    $grpcWorker = new RoadRunner\Grpc\GrpcWorker($worker, new MyGrpcService());
    

4. Dependency Injection

  • Laravel Container: Bind RoadRunner workers to Laravel’s service container:
    $app->singleton(RoadRunner\Worker::class, function () {
        return RoadRunner\Worker::create();
    });
    

5. Hot Reloading

  • Use SIGUSR2 for graceful reloads (requires .rr.yaml symlink):
    server:
      reload:
        enabled: true
    

Gotchas and Tips

Pitfalls

  1. PHP Extensions:

    • Ensure php-sockets is installed (php --modules). Missing it causes EOF errors.
    • RoadRunner uses Go’s net package; ensure your PHP process has socket permissions.
  2. Configuration Overrides:

    • Environment variables in .rr.yaml (e.g., env: APP_ENV=${APP_ENV}) are not interpolated by default. Use rr serve --env APP_ENV=local or a .env loader plugin.
  3. Worker Isolation:

    • RoadRunner spawns workers per request (default). For long-running tasks, use the jobs plugin or worker_pool:
      worker_pool:
        num_workers: 8
      
  4. TLS Management:

    • Automatic TLS requires certificates in .rr.yaml:
      http:
        tls:
          cert: "/path/to/cert.pem"
          key: "/path/to/key.pem"
      
  5. Plugin Conflicts:

    • Avoid mixing fileserver and http plugins for the same port. Use port: 8080 and fileserver_port: 8081.

Debugging Tips

  1. Logs:

    • Set logs.level: debug in .rr.yaml for verbose output.
    • Use rr logs to stream logs in real-time.
  2. Metrics:

    • Enable Prometheus middleware:
      http:
        middleware: ["prometheus"]
      
    • Access metrics at http://localhost:8080/metrics.
  3. Worker Crashes:

    • Check Go’s error logs (rr logs --level debug). Common causes:
      • Unhandled PHP exceptions (wrap in try-catch).
      • Missing dependencies (e.g., php-curl for HTTP plugins).
  4. Performance:

    • Monitor worker pool size (worker_pool.num_workers). Too many workers cause memory bloat; too few throttle requests.
    • Use autoscaling for dynamic workloads:
      worker_pool:
        autoscaling:
          min_workers: 2
          max_workers: 16
      

Extension Points

  1. Custom Plugins:

    • Write Go plugins using RoadRunner’s plugin SDK. Example: A custom KV store plugin for Laravel’s cache.
  2. Middleware Chaining:

    • Combine Laravel middleware with RoadRunner middleware:
      $middlewareStack = new \Laravel\Middleware\Pipeline($app);
      $middlewareStack->send($request)->through([...]);
      
  3. Telemetry:

    • Integrate OpenTelemetry:
      otel:
        service_name: "my-app"
        exporter: "jaeger"
      
  4. Systemd Integration:

    • Use RoadRunner’s systemd plugin for process management:
      systemd:
        enabled: true
        service_name: "my-app"
      

Laravel-Specific Quirks

  1. Service Provider Bootstrapping:

    • RoadRunner workers run outside Laravel’s bootstrapping. Manually register providers:
      $app = require __DIR__.'/bootstrap/app.php';
      $app->make(Kernel::class)->bootstrap();
      
  2. Request Lifecycle:

    • Laravel’s Request class won’t work directly. Use PSR-7 adapters:
      use Illuminate\Http\Request;
      $request = Request::createFromBase($psrRequest);
      
  3. Queue Listeners:

    • Replace Laravel’s queue listeners with RoadRunner’s job plugin. Example:
      $jobWorker = new RoadRunner\Job\JobWorker($worker);
      while ($job = $jobWorker->wait()) {
          $job->setPayload(json_decode($job->getPayload(), true));
          app()->make(HandleJobs::class)->handle($job);
          $job->ack();
      }
      
  4. Artisan Commands:

    • RoadRunner doesn’t support Artisan by default. Use a separate process or the cli plugin:
      cli:
        command: "php artisan queue:work"
      
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.
codraw/entity-migrator
codraw/doctrine-extra
codraw/aws-tool-kit
codraw/validator
codraw/workflow
codraw/open-api
codraw/cron-job
codraw/process
codraw/log
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony