Skip to main content
composer require asyncbase/asyncbase

Configure

.env
ASYNCBASE_KEY=sk_live_...

Plain PHP

<?php
require 'vendor/autoload.php';
use AsyncBase\Queue;

$q = new Queue(getenv('ASYNCBASE_KEY'));
$r = $q->send('emails', ['to' => 'a@b.com'], delay: '30s');

foreach ($q->pull('emails', group: 'workers', limit: 10, waitSeconds: 5) as $msg) {
    try {
        handle($msg->payload);
        $msg->ack();
    } catch (\Throwable $e) {
        $msg->nack();
    }
}

Laravel service provider

app/Providers/AppServiceProvider.php
use AsyncBase\Queue;

public function register(): void
{
    $this->app->singleton(Queue::class, fn () =>
        new Queue(env('ASYNCBASE_KEY'))
    );
}

Controller

use AsyncBase\Queue;

class EmailController extends Controller
{
    public function __construct(private readonly Queue $queue) {}

    public function send(Request $req): JsonResponse
    {
        $r = $this->queue->send('emails', $req->validated(), delay: '30s');
        return response()->json(['id' => $r->id]);
    }
}

Artisan consumer

app/Console/Commands/ConsumeEmails.php
use AsyncBase\Queue;
use Illuminate\Console\Command;

class ConsumeEmails extends Command
{
    protected $signature = 'asyncbase:consume';

    public function handle(Queue $q): int
    {
        foreach ($q->consume('emails', group: 'laravel-workers', visibilitySeconds: 60) as $msg) {
            try { handle($msg->payload); $msg->ack(); }
            catch (\Throwable $e) { $msg->nack(); }
        }
        return self::SUCCESS;
    }
}
Run under supervisor:
[program:asyncbase-consume]
command=php /var/www/html/artisan asyncbase:consume
autostart=true
autorestart=true
user=www-data

Error handling

PHP’s built-in Exception uses $code for an integer, so the error code is on $errorCode.
use AsyncBase\AsyncBaseError;

try {
    $q->send('emails', [...]);
} catch (AsyncBaseError $e) {
    if ($e->errorCode === 'RATE_LIMITED') {
        sleep(1);
    } else {
        throw $e;
    }
}