paulemich/laravel-asb

Azure Service Bus queue driver for Laravel (asb), supporting delay, retry/backoff and dead-lettering. Built on paulemich/azure-service-bus.

Maintainers

Package info

github.com/PaulEmich/laravel-asb

pkg:composer/paulemich/laravel-asb

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-06-03 10:16 UTC

This package is auto-updated.

Last update: 2026-06-03 10:19:32 UTC


README

Latest Version on Packagist Total Downloads License

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 Send and Listen (and Manage if you want queue:monitor counts).

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 increments DeliveryCount and redelivers it. This is fully native — set the queue's MaxDeliveryCount in Azure and exhausted messages are moved to the dead-letter sub-queue automatically.
  • Delayed retry ($backoff, or release($seconds) with a delay): the Service Bus REST API cannot "abandon with a delay", so the driver schedules a fresh copy with ScheduledEnqueueTimeUtc and completes the original. The attempt count is carried forward in a custom message property so attempts() stays correct.

Tip: For jobs that use $backoff, rely on Laravel's $tries / retryUntil() to bound retries rather than the queue's MaxDeliveryCount, 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 returns 0 (there is no locked/in-flight count).
  • creationTimeOfOldestPendingJob() always returns null.

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.