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

Beanstalk Queue Driver Bundle Laravel Package

mcfedr/beanstalk-queue-driver-bundle

Symfony bundle that integrates a Beanstalkd queue driver with the mcfedr queue library, letting Symfony applications dispatch and process background jobs through Beanstalkd.

View on GitHub
Deep Wiki
Context7

Getting Started

The first thing to internalize: this is a Symfony bundle, not a Laravel package. There is no ServiceProvider, no config/queue.php hook, no Illuminate\Queue\Connector implementation, and no auto-discovery. Laravel will not register it, and even if it did, the services it wires would land in a Symfony container you don't have.

So the "getting started" path for a Laravel developer splits into two:

Path A — You are on Laravel and just want Beanstalkd (the 99% case). Use the framework. Nothing in this repo is required.

  1. composer require pda/pheanstalk
  2. Run Beanstalkd locally (beanstalkd -p 11300 -b /var/lib/beanstalkd) or point at a managed instance.
  3. In config/queue.php, set:
    'beanstalkd' => [
        'driver' => 'beanstalkd',
        'host' => env('BEANSTALKD_HOST', '127.0.0.1'),
        'queue' => env('BEANSTALKD_QUEUE', 'default'),
        'retry_after' => 90,
        'block_for' => 5,
    ],
    
  4. QUEUE_CONNECTION=beanstalkd in .env.
  5. First job: php artisan make:job SendWelcomeEmail implements ShouldQueue, dispatch it, then php artisan queue:work --queue=default. That's the whole loop.

Path B — You are on a mixed Symfony+PHP stack, or evaluating whether to adopt this bundle. Read the source, in this order: src/DependencyInjection/*Extension.php (real config keys), Resources/config/services.* (service IDs), then the underlying mcfedr/beanstalk-queue-driver (this bundle is just DI glue — the driver is where job serialization lives). Look for the mcfedr/queue-driver interface to see what abstraction the driver implements. There is no Flex recipe, so manual registration in config/bundles.php (or AppKernel::registerBundles()) is required.

First use case (Path A): a single-priority queue for latency-sensitive work — e.g. transactional email ahead of bulk report generation. That's the one workflow where Beanstalkd actually earns its keep on Laravel and where this bundle is nominally relevant — as a reference for how Beanstalkd's priorities/delay/TTR map to jobs.

Implementation Patterns

If you're doing Beanstalkd on Laravel, the patterns below are the ones you'll live in daily. If you're on Symfony and evaluating this bundle, the same patterns apply — just swap the wiring.

Priority-based job routing. Beanstalkd supports numeric priorities (lower = higher priority). Laravel's native driver exposes one tube per connection queue, so the pattern is one connection per priority class:

'beanstalkd' => [... 'queue' => 'default'],        // priority 1024
'beanstalkd-critical' => [... 'queue' => 'critical', 'driver' => 'beanstalkd'],

Then SendWelcomeEmail::dispatch()->onConnection('beanstalkd-critical'). Workers pull in priority order: php artisan queue:work --queue=critical,default. This is where Beanstalkd's model maps directly to a product requirement ("transactional email before bulk reports").

Delayed retries and backoff. Use $job->release($delay) in a handle() catch block for fine-grained backoff. Beanstalkd's delay maps to Laravel's delayed dispatch: SendWelcomeEmail::dispatch()->delay(now()->addMinutes(5)) sets a delay-until. Prefer explicit release() over retry_after when you need varied backoff per failure type — retry_after is a single global knob per connection.

TTR / timeout enforcement. retry_after in config/queue.php maps to Beanstalkd's TTR (time-to-reserve). If a job runs longer than retry_after, the job is re-reserved and runs concurrently with the still-running original. Set $timeout on jobs below retry_after (Laravel's default 60s timeout vs 90s retry_after is the safe ratio). For anything approaching TTR, redesign — Beanstalkd will not heartbeat for you.

Tube-per-tenant or tube-per-domain. Beanstalkd tubes are cheap and isolated. Pattern: queue:work --queue=tenant_42,default with tenant jobs dispatched to tenant_{$id}. This gives you per-tenant throttling and a way to pause a noisy customer without touching others.

Bury/kick for dead-letter handling. Beanstalkd's bury is the native dead-letter. Laravel's failed_jobs table captures failures before bury happens if you use the framework path; if you're operating the driver directly (i.e., a Symfony-style integration), you are the bury policy — decide whether to bury, retry, or delete on the catch block.

Wrapper interface (the actual recommendation). Whatever you do, hide the driver behind an app interface:

interface JobQueue {
    public function push(string $jobClass, array $payload, int $priority = 1024, ?int $delay = null): void;
}

Bind it to a BeanstalkdJobQueue implementation in a service provider. This costs an afternoon and buys you a Redis/SQS swap without touching call sites — the single most useful pattern if you're considering anything from this repo's ecosystem.

If you're specifically extracting from mcfedr/beanstalk-queue-driver for a Symfony-Laravel hybrid: vendor the driver, write a ConnectorInterface implementation and a Queue subclass that maps Laravel's job envelope (displayName, attempts, timeout) onto the driver's job struct. This is a spike, not a dependency — and you'll hit the envelope mismatch immediately (see Gotchas).

Gotchas and Tips

Don't install it in a Laravel app. composer require mcfedr/beanstalk-queue-driver-bundle will succeed, add the package, and do nothing usable — no provider, no config, no connector. You'll then spend an hour debugging why Queue::connection('beanstalkd-symfony') fails. The failure mode is silent.

Job payload format mismatch is the #1 integration trap. Laravel's driver serializes {"uuid":..., "displayName":"App\\Jobs\\X", "job":"Illuminate\\Queue\\CallQueuedHandler@call", "data":{"commandName":"App\\Jobs\\X","command":"..."}, "attempts":N, "timeout":M}. A Symfony/other driver's envelope will differ (often CommandName@method or a class-name + argument list). If you extract the driver and hand-wire it, jobs dispatched through one path will not be consumable by workers on the other. Diff the envelopes before you write a line of glue.

retry_after vs $timeout vs --timeout is a three-way footgun. Workers get --timeout (Laravel kills at N seconds via SIGALRM), jobs get $timeout (same, per-job), and the connection retry_after is when Beanstalkd re-reserves. All three must be ordered: $timeout < --timeout < retry_after. Get this wrong and you get duplicate execution under load — never at low load, always at 2am.

--sleep and --block_for change CPU behavior dramatically. block_for => 5 means the worker blocks on reserve for 5s. block_for => 0 means it polls. Workers left at block_for=0 on a sleep=0 loop will peg a CPU doing nothing. Set block_for in config/queue.php and leave it alone.

Bury/kick has no Laravel surface. Beanstalkd buried jobs are invisible to queue:failed and failed_jobs. Build an artisan command (php artisan beanstalkd:peek-buried, :kick) using Pheanstalk::peekBuried() and kick(). Without it, your "dead letters" are a black hole.

No clustering, no replication, no HA. Beanstalkd is a single binary with an append-only binlog. There is no failover. If your job must run or must run exactly once, Beanstalkd is the wrong tool — this is a server property, not a driver property, and no bundle fixes it. Accept at-least-once semantics and make jobs idempotent.

No scheduled/cron-style jobs, no fan-out, no pub/sub. "Run this daily at 3am" is Laravel's scheduler (routes/console.php + schedule:run), not the queue. Fan-out is multiple job dispatches within a transaction, not a Beanstalkd feature.

TTR re-reservation is silent. A long-running job (> retry_after) does not error — Beanstalkd quietly hands it to another worker. You see duplicated side effects, not an exception. This is the hardest failure mode to debug in production; instrument job duration and alert at 75% of retry_after.

On the package itself: ~1 star, 0 dependents, single maintainer, no release cadence, no security process. If you adopt it (Symfony side), pin the exact version in composer.json, vendor it into your repo, and treat the upstream as abandoned. Budget for a fork. The MIT license means the fork is legal; nothing else is guaranteed.

Extension point, if you're already invested: the driver (not the bundle) is the layer to wrap. Override the Connector (Laravel) or the DI service (Symfony) to inject your own serializer — this is where you'd add job-envelope versioning, payload encryption, or a JobQueue interface shim. Don't fork the bundle; fork the driver and depend on it via a path repository.

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.
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin