jeffersongoncalves / laravel-queue-worker
Receive Laravel queue job payloads from ephemeral review environments over HTTP and execute them in their originating environment via Horizon.
Package info
github.com/jeffersongoncalves/laravel-queue-worker
pkg:composer/jeffersongoncalves/laravel-queue-worker
Requires
- php: ^8.2
- illuminate/bus: ^12.0|^13.0
- illuminate/console: ^12.0|^13.0
- illuminate/contracts: ^12.0|^13.0
- illuminate/http: ^12.0|^13.0
- illuminate/process: ^12.0|^13.0
- illuminate/queue: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.21
- orchestra/testbench: ^10.0|^11.0
- pestphp/pest: ^3.0|^4.0
- pestphp/pest-plugin-laravel: ^3.0|^4.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-06 00:34:41 UTC
README
Laravel Queue Worker
Receive Laravel queue job payloads over HTTP from many ephemeral review environments and execute them, each inside its own originating environment, from a central "hub" application backed by Horizon.
This is the hub-side counterpart to jeffersongoncalves/laravel-queue-consumer. At least one environment running that package is required to send this package any jobs — installing this package alone receives nothing on its own.
How it works
Dozens of ephemeral review environments (one Laravel application per git branch, spun up and torn down by CI, each with its own vendor/, .env, and its own version of the application code) run laravel-queue-consumer, which POSTs job payloads here instead of running a local queue worker.
This package:
- Accepts
POST /api/jobs, authenticates it, and validates the environmentpathit was given. - Queues a
RunEnvironmentJobonto Horizon/Redis — nothing runs synchronously inside the HTTP request. - When that job runs, it spawns a child PHP process inside the originating environment's own directory, running
artisan queue-consumer:runthere, so the job executes with that environment's own autoloader, code, and database connection — never inside this hub application's own process.
Installation
You can install the package via composer:
composer require jeffersongoncalves/laravel-queue-worker
The package uses Laravel's auto-discovery, so the service provider is registered automatically.
Publish configuration
php artisan vendor:publish --tag=queue-worker-config
This publishes config/queue-worker.php:
return [ 'token' => env('QUEUE_WORKER_TOKEN'), 'allowed_root' => env('QUEUE_WORKER_ALLOWED_ROOT'), 'route_prefix' => env('QUEUE_WORKER_ROUTE_PREFIX', 'api'), 'route_middleware' => ['api'], 'dedup_window_hours' => env('QUEUE_WORKER_DEDUP_WINDOW_HOURS', 24), 'php_binary_map' => [ // '8.1' => '/usr/bin/php8.1', // '8.2' => '/usr/bin/php8.2', // '8.3' => '/usr/bin/php8.3', ], ];
Environment setup
QUEUE_WORKER_TOKEN=some-shared-secret-token QUEUE_WORKER_ALLOWED_ROOT=/srv/environments QUEUE_WORKER_DEDUP_WINDOW_HOURS=24
QUEUE_WORKER_TOKEN has no default and is required. The X-Laravel-Queue-Token header of every incoming request is compared against it using a constant-time hash_equals() check. If the header is missing or wrong, the request is rejected with 403. If the token itself is left unconfigured, the package refuses to process any request at all — it never falls back to accepting unauthenticated traffic.
QUEUE_WORKER_ALLOWED_ROOT has NO default value on purpose, and this is a loud warning: you must set it. Every incoming path is resolved with realpath() and must live inside this directory, must contain an artisan file directly inside it, and its basename must match the request's slug field (i.e. an environment at /srv/environments/app-feature-1234 must be posted with "slug": "app-feature-1234"). If allowed_root is not configured, every single request is rejected with 422 — the package never falls back to "allow everything" or "allow the current working directory".
php_binary_map maps an environment's own composer.json require.php constraint (major.minor, e.g. 8.2 from ^8.2) to a concrete PHP binary on the host running this package. There is no fallback to this hub's own php binary: an environment whose PHP version isn't mapped causes the job to throw loudly, rather than silently running someone else's job under the wrong PHP version.
Optional: distinguishing failed jobs by environment
This package can optionally add nullable slug and display_name columns to your failed_jobs table, so failed jobs from many environments are distinguishable in a listing without cross-referencing path. This migration is not run automatically — publish and run it yourself if you want it:
php artisan vendor:publish --tag=queue-worker-migrations php artisan migrate
The migration is written defensively: it checks whether failed_jobs exists and whether each column already exists before adding it.
Protocol
POST {route_prefix}/jobs (default /api/jobs), with header X-Laravel-Queue-Token:
{
"slug": "app-feature-1234",
"path": "/srv/environments/app-feature-1234",
"queue": "default",
"delay": 0,
"payload": "<opaque string, exactly what Laravel's own createPayload() produced in the originating environment>"
}
A successful response is 202 with {"id": "<hub job id>"} (the uuid read off the payload). Delivery is at-least-once: the consumer package may resend an identical request if it loses the response, so this package deduplicates by the payload's uuid for dedup_window_hours (default 24h).
This package never deserializes the job payload itself. It only reads the outer bookkeeping fields via json_decode (uuid, displayName, maxTries, timeout) and forwards the payload string, untouched, to the child process — where the consumer package's own queue-consumer:run command unserializes it, in the originating environment, with that environment's own autoloader.
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
This package is for internal, trusted review environments only. It must never be exposed to the public internet and must never run in production. allowed_root and the token are the only things standing between an HTTP request and arbitrary process execution on the host running this package — treat both accordingly. Please review our security policy on how to report security vulnerabilities.
Limitations
- No built-in dashboard — use Horizon's own dashboard for queue visibility and job tags (
env:<slug>,job:<displayName>). - No discovery or garbage collection of stale environment directories: if an environment is torn down, its queued jobs are simply discarded once they run and find the path gone.
- No support for non-Laravel consumers — the protocol assumes the sender is
jeffersongoncalves/laravel-queue-consumer.
Credits
License
The MIT License (MIT). Please see License File for more information.
