paulemich / laravel-asb
Azure Service Bus queue driver for Laravel (asb), supporting delay, retry/backoff and dead-lettering. Built on paulemich/azure-service-bus.
Requires
- php: ^8.3
- ext-json: *
- illuminate/queue: ^13.0
- illuminate/support: ^13.0
- paulemich/azure-service-bus: *
Requires (Dev)
- mockery/mockery: ^1.6
- orchestra/testbench: ^11.0
- pestphp/pest: ^4.0
This package is auto-updated.
Last update: 2026-06-03 10:19:32 UTC
README
An Azure Service Bus queue driver for Laravel, registered as the asb connection — the Azure counterpart to Laravel's built-in sqs driver. It plugs straight into Laravel's queue system, so dispatch(), ->delay(), $tries, $backoff, release(), failed(), and dead-lettering all work as you'd expect.
It talks to Service Bus over the REST API (no PHP extensions required) and is built on the framework-agnostic paulemich/azure-service-bus client.
Features
| Laravel feature | How it maps to Azure Service Bus |
|---|---|
dispatch($job) |
Message sent to the queue (peek-lock on receive) |
->delay($seconds) / Queue::later() |
Native ScheduledEnqueueTimeUtc scheduled delivery |
$job->attempts() |
Native DeliveryCount |
| Retry after failure | Native message abandon (immediately redelivered) |
$tries exhausted |
Honoured by the worker; combine with the queue's MaxDeliveryCount for native dead-lettering |
$backoff (delayed retry) |
Reschedules the message with ScheduledEnqueueTimeUtc, carrying the attempt count forward |
queue:clear |
Drains the queue via destructive receive |
Requirements
- PHP 8.3+
- Laravel 13+
- An Azure Service Bus namespace with a queue and a SAS policy that grants
SendandListen(andManageif you wantqueue:monitorcounts).
Installation
composer require paulemich/laravel-asb
The service provider is auto-discovered and registers the asb queue connector.
Configuration
The package ships with sensible, env-driven defaults that are merged into queue.connections.asb, so the quickest setup is just environment variables:
QUEUE_CONNECTION=asb # Option A — a full connection string (copy it from the Azure portal): ASB_CONNECTION_STRING="Endpoint=sb://my-namespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=your-key" # Option B — discrete credentials (use one option or the other): ASB_NAMESPACE=my-namespace # short name OR full host (my-namespace.servicebus.windows.net) ASB_KEY_NAME=RootManageSharedAccessKey ASB_KEY=your-key ASB_QUEUE=default # the queue (entity) to use ASB_WAIT=30 # peek-lock long-poll seconds # ASB_TTL=3600 # optional default message TTL (seconds) # ASB_TOKEN_TTL=3600 # SAS token lifetime (seconds)
If you prefer to manage everything in config/queue.php (the standard Laravel way), add an explicit connection block:
'connections' => [ // ... 'asb' => [ 'driver' => 'asb', 'connection_string' => env('ASB_CONNECTION_STRING'), // or the discrete credentials: 'namespace' => env('ASB_NAMESPACE'), 'shared_access_key_name' => env('ASB_KEY_NAME'), 'shared_access_key' => env('ASB_KEY'), 'queue' => env('ASB_QUEUE', 'default'), 'wait' => (int) env('ASB_WAIT', 30), 'ttl' => env('ASB_TTL') !== null ? (int) env('ASB_TTL') : null, 'token_ttl' => (int) env('ASB_TOKEN_TTL', 3600), 'after_commit' => false, ], ],
When a connection_string is present it takes precedence; otherwise the discrete namespace / shared_access_key_name / shared_access_key are used. namespace accepts either a short name (my-namespace) or a fully-qualified host (my-namespace.servicebus.windows.net).
Usage
Use it like any other queue connection.
// Dispatch to the default ASB queue ProcessPodcast::dispatch($podcast); // Delay (native scheduled delivery) ProcessPodcast::dispatch($podcast)->delay(now()->addMinutes(10)); // Target a specific queue ProcessPodcast::dispatch($podcast)->onQueue('media'); // Run a worker against the connection // php artisan queue:work asb // php artisan queue:work asb --queue=media
Third-party package jobs work unchanged — the driver only wraps the transport envelope; your job class is serialized into the message payload exactly as with any other driver.
Retries, backoff & dead-lettering
There are two retry paths, and which one runs depends on whether the job asks for a delay:
- Immediate retry (a job released without a delay, e.g. a thrown exception with no
$backoff): the message is abandoned natively. Service Bus incrementsDeliveryCountand redelivers it. This is fully native — set the queue'sMaxDeliveryCountin Azure and exhausted messages are moved to the dead-letter sub-queue automatically. - Delayed retry (
$backoff, orrelease($seconds)with a delay): the Service Bus REST API cannot "abandon with a delay", so the driver schedules a fresh copy withScheduledEnqueueTimeUtcand completes the original. The attempt count is carried forward in a custom message property soattempts()stays correct.
Tip: For jobs that use
$backoff, rely on Laravel's$tries/retryUntil()to bound retries rather than the queue'sMaxDeliveryCount, since each delayed retry is a freshly scheduled message.
To enable native dead-lettering for the immediate-retry path, set Max Delivery Count on the queue in the Azure portal (Queue → Settings) or via your IaC of choice.
Queue monitoring
Queue::connection('asb')->size() reports active + scheduled messages. pendingSize() and delayedSize() map to the active and scheduled counts respectively. Two methods return fixed values because Service Bus does not expose them over REST:
reservedSize()always returns0(there is no locked/in-flight count).creationTimeOfOldestPendingJob()always returnsnull.
Reading counts requires a SAS policy with the Manage claim.
Artisan commands
The package ships a few diagnostic commands for poking at a live queue and seeing exactly what the driver does. They all accept --connection= (default asb) and --queue= (defaults to the connection's configured queue).
# Show message counts: the driver methods (size/pending/delayed/reserved) and # the raw Service Bus breakdown (active/scheduled/dead-letter/total). php artisan asb:counts # Send messages. Generates a JSON probe payload when no body is given. php artisan asb:send # one probe message php artisan asb:send '{"hello":"world"}' # a literal body php artisan asb:send --count=5 --delay=30 # five messages, scheduled 30s out php artisan asb:send --property=Priority=high --property=Tenant=acme # Peek-lock receive a single message and print its broker properties, custom # properties and body. --ack controls settlement: abandon (default), complete, hold. php artisan asb:receive --wait=10 --ack=complete # Remove all available messages from the queue. php artisan asb:purge
Testing
composer install vendor/bin/pest
The suite uses Orchestra Testbench and mocks the Service Bus client, so no Azure account or network access is needed.
License
The MIT License (MIT). See LICENSE.md.