Queues & Jobs
Background jobs handle all work that should not block an HTTP response — PDF generation, search index updates, notifications, and ERP exports. Laravel Horizon manages workers and provides visibility into queue health.
Queue Priority Configuration
// config/horizon.php
'environments' => [
'production' => [
'billing-worker' => [
'connection' => 'redis',
'queue' => ['billing', 'default'],
'balance' => 'auto',
'minProcesses' => 2,
'maxProcesses' => 5,
],
'default-worker' => [
'connection' => 'redis',
'queue' => ['default', 'notifications', 'sync'],
'balance' => 'simple',
'processes' => 3,
],
],
],
| Queue | Priority | Jobs |
|---|---|---|
billing | High | Invoice PDF generation, ERP export flush |
default | Normal | Document processing, search indexing |
notifications | Low | Email and push notifications |
sync | Low | Meilisearch index sync |
Job Inventory
GenerateInvoicePdfJob
Queue: billing
Calls InvoiceGeneratorService::generatePdf(Invoice $invoice), renders the Blade
template via spatie/laravel-pdf, uploads the PDF to S3 via Media Library, stores the
S3 key on the invoice record, dispatches InvoicePdfReadyNotification.
Retry: 3 attempts with exponential backoff. Financial jobs must never silently fail —
failed jobs are preserved in failed_jobs for manual inspection.
FlushErpExportQueueJob
Queue: billing
Reads pending rows from erp_export_queue, maps them through ErpPostingRules, posts
to the ERP endpoint, marks rows as exported. Runs on a scheduled basis (daily).
SyncMeilisearchIndexJob
Queue: sync
Re-indexes a model class (e.g., Matter, Client) in Meilisearch after bulk changes.
Dispatched after mass updates or imports.
SendNotificationJob
Queue: notifications
Wraps a Laravel Notification and dispatches it to the appropriate channel (database,
mail, Reverb broadcast). Decouples notification delivery from the triggering request.
ProcessDocumentJob
Queue: default
After a document is uploaded to S3 (via presigned URL), this job verifies the upload
exists, updates document status from PENDING_UPLOAD to DRAFT, and triggers search
indexing.
Failed Job Handling
# View failed jobs
php artisan queue:failed
# Retry a specific failed job
php artisan queue:retry {id}
# Retry all failed billing jobs
php artisan queue:retry --queue=billing
Financial jobs (GenerateInvoicePdfJob, FlushErpExportQueueJob) must never be retried
blindly — inspect the failure reason first to avoid duplicate invoice creation.