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

Torque Laravel Package

webpatser/torque

Torque is a lightweight Laravel package by webpatser that offers a clean, fluent API for common application tasks. It integrates smoothly into existing Laravel projects and is easy to install and configure, making it a practical choice for small projects and rapid prototyping.

View on GitHub
Deep Wiki
Context7

Getting Started

Torque is a Redis Streams queue driver for Laravel with Fiber-based concurrency. The shortest path from zero to a confident decision:

  1. Install and publish config
    composer require <vendor>/torque
    php artisan vendor:publish --tag=torque-config
    
  2. Add a connection in config/queue.php alongside your existing redis connection (don't overwrite it — you'll want it for comparison):
    'torque' => [
        'driver'     => 'torque',
        'connection' => 'default',
        'queue'      => 'default',
        'serializer' => env('TORQUE_SERIALIZER', 'json'),
        // concurrency / group / block settings per config/torque.php
    ],
    
  3. Read two files before writing any code: the README's "When to use Torque" / "When to use Horizon instead" sections, and BENCHMARKS.md including its "what this benchmark does NOT measure" section. These are written to let you self-select out, which is the single most valuable thing in the docs.
  4. Start a master and check status
    php artisan torque:start      # prints "Serializer: igbinary" if enabled, or an install hint if the ext is missing
    php artisan torque:status
    
  5. Benchmark your own box before migrating a real workload
    php artisan torque:bench --use-running-master --workload=async-io
    

Your first real use case should be async I/O fan-out: handlers that spend their time waiting on HTTP, Redis, or a socket — exactly the async-io and fanout profiles where the release claims up to 15x throughput and 95% lower memory versus queue:work. If your jobs are CPU-bound or dominated by blocking SQL, benchmarking first will save you a migration.

Implementation Patterns

Keep handlers Fiber-friendly — this is the whole ballgame. The README's new "Working with databases (avoid the Eloquent trap)" section is required reading. Eloquent "works," but a blocking PDO call parks the Fiber and collapses your fan-out back to serial behaviour. Two patterns:

// Pre-fetch at dispatch time — keeps the handler pure and Fiber-safe
ProcessOrder::dispatch($order->only(['id', 'total', 'customer_id']));

// Or route reads through the pool inside the handler
public function handle(MysqlPool $pool): void
{
    $row = $pool->selectOne('select * from orders where id = ?', [$this->orderId]);
    // ...
}

Pick the serializer per workload, not globally. JSON stays the default and should stay your default in dev — redis-cli XRANGE remains readable, which is worth more than throughput on small payloads where igbinary shows "no measurable difference." Flip TORQUE_SERIALIZER=igbinary only for queues carrying large payloads, where encode/decode roughly halves. Because the decode path sniffs the leading byte, you can flip it on a running cluster and let in-flight JSON messages drain organically — treat that as your deployment story rather than a coordinated restart.

Use torque:bench as a CI gate, not a one-off. The --json=path (or --json=- for stdout) schema is designed for diffing:

php artisan torque:bench --use-running-master --workload=mixed --json=storage/bench/$(date +%F).json

Commit the JSON alongside the change that caused it. Throughput regressions from a concurrency tweak are otherwise invisible until production.

Mirror the Horizon kit when you need to justify the choice. bench/horizon-comparison/ gives you HorizonBenchJob, a standalone run-horizon-bench.php that auto-detects the host app from cwd, and a README. Run both sides on your hardware instead of quoting BENCHMARKS.md in a design review — the numbers are host-specific and reviewers know it.

Tune concurrency to the workload profile, not to a single global number. The seven profiles (cpu, io, async-io, fanout, mixed, payload-small, payload-large) exist precisely because the optimum diverges; a Fibre count that wins on async-io will oversubscribe on cpu.

Surface live job progress as a first-class UX feature. It's positioned in this release as a differentiator versus Horizon; if you're migrating, wire progress broadcasting into your handlers early rather than bolting it on later.

Gotchas and Tips

  • Upgrade to ≥0.8.0 before touching igbinary. Prior versions crash in StreamJob::__construct with a TypeError on the readonly array payload property when the body is binary — jobs pile up and the tail times out with no obvious cause. The bug was incidentally hidden because the JSON path was the only one exercised.
  • Mixed JSON/igbinary payloads are safe but opaque. decodePayload/isValidPayload sniff both formats, so workers won't drop binary blobs as "corrupt" (the old json_validate check in WorkerProcess::processMessage did exactly that). But a queue with mixed formats is unreadable in redis-cli; when debugging, check the first byte ({, [, or \x00\x00\x00\x02) before assuming corruption.
  • serializer must reach the connection config, not just config/torque.php. StreamConnector::connect() reads 'serializer' off the queue connection array. If you set the env var but your queue.php entry doesn't reference it, you'll silently stay on JSON.
  • Bench v1 requires --use-running-master. Self-spawning workers land in v1.1; expect a hard failure (not a fallback) if you forget to start a master first.
  • Don't expect per-stage timings yet. BenchProbe is wired but the serialize / xadd / xreadgroup / unserialize / handle / xack breakdown is explicitly v1.1. Today you get throughput, p50/p95/p99 end-to-end latency, and median handle duration — useful for spotting a regression, not for attributing it.
  • The Eloquent compatibility row means "runs," not "scales." Read the table as a correctness statement, not a performance one.
  • composer.json only suggests ext-igbinary. Nothing enforces it; a deploy to a host without the extension leaves you on JSON (with a torque:start hint) rather than failing — check the startup line in your process supervisor logs to confirm which serializer is actually live.
  • Extension points to know: StreamQueue::encodePayload / transcodeIncomingPayload (private) and decodePayload / isValidPayload (public static) are the seam if you ever need a third format; the Bench* console classes under src/Console/Bench/ are live and aggregator-driven, so custom profiles are a plausible fork point.
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.
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
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource