{"id":36976432,"url":"https://github.com/lettermint/laravel-rabbitmq","last_synced_at":"2026-01-13T22:43:29.995Z","repository":{"id":329791178,"uuid":"1120030027","full_name":"lettermint/laravel-rabbitmq","owner":"lettermint","description":"An experimental implementation of RabbitMQ concepts in Laravel.","archived":false,"fork":false,"pushed_at":"2026-01-02T23:54:32.000Z","size":449,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-07T02:03:48.341Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lettermint.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-20T10:40:24.000Z","updated_at":"2026-01-02T23:54:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lettermint/laravel-rabbitmq","commit_stats":null,"previous_names":["lettermint/laravel-rabbitmq"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/lettermint/laravel-rabbitmq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lettermint%2Flaravel-rabbitmq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lettermint%2Flaravel-rabbitmq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lettermint%2Flaravel-rabbitmq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lettermint%2Flaravel-rabbitmq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lettermint","download_url":"https://codeload.github.com/lettermint/laravel-rabbitmq/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lettermint%2Flaravel-rabbitmq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28400753,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-13T22:43:29.419Z","updated_at":"2026-01-13T22:43:29.986Z","avatar_url":"https://github.com/lettermint.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laravel RabbitMQ\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/lettermint/laravel-rabbitmq.svg?style=flat-square)](https://packagist.org/packages/lettermint/laravel-rabbitmq)\n[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/lettermint/laravel-rabbitmq/run-tests.yml?branch=main\u0026label=tests\u0026style=flat-square)](https://github.com/lettermint/laravel-rabbitmq/actions?query=workflow%3Arun-tests+branch%3Amain)\n[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/lettermint/laravel-rabbitmq/fix-php-code-style-issues.yml?branch=main\u0026label=code%20style\u0026style=flat-square)](https://github.com/lettermint/laravel-rabbitmq/actions?query=workflow%3A\"Fix+PHP+code+style+issues\"+branch%3Amain)\n[![Total Downloads](https://img.shields.io/packagist/dt/lettermint/laravel-rabbitmq.svg?style=flat-square)](https://packagist.org/packages/lettermint/laravel-rabbitmq)\n\n**A production-ready RabbitMQ queue driver for Laravel with attribute-based topology, automatic retries, and Kubernetes-native deployment.**\n\nBuild resilient, scalable queue systems using RabbitMQ's powerful routing with Laravel's familiar job syntax. No Horizon required.\n\n## ✨ Features\n\n- 🎯 **Attribute-Based Topology** - Define exchanges and queues using PHP 8 attributes on your job classes\n- 🔄 **Automatic Retries \u0026 DLQ** - Built-in dead letter queues with configurable retry strategies\n- 📊 **Priority Queues** - Support for message priorities (0-255) on classic queues\n- ⏰ **Delayed Messages** - Schedule jobs with native RabbitMQ delayed message exchange\n- 🚀 **Laravel-Native** - Works with standard `dispatch()` - no learning curve\n- ☸️ **Kubernetes-Ready** - Custom consumer commands designed for containerized deployments\n- 💪 **Production-Proven** - Built on php-amqplib with heartbeat support and publisher confirms\n\n## 🤔 Why Use RabbitMQ?\n\nThis package is ideal for applications that need:\n\n- **Advanced Routing** - Route messages based on patterns, headers, or broadcast to multiple queues\n- **Guaranteed Delivery** - RabbitMQ's persistence and publisher confirms ensure messages aren't lost\n- **Complex Workflows** - Multi-tenant systems, event-driven architectures, microservices communication\n- **Infrastructure-Level Control** - Manage queue topology, clustering, and federation through RabbitMQ itself\n- **Kubernetes-Native Workers** - Deploy queue consumers as standard Kubernetes Deployments with HPA\n- **Protocol Flexibility** - AMQP protocol support for cross-platform messaging (Node.js, Python, Go, etc.)\n\n## 📋 Requirements\n\n- PHP 8.2+\n- Laravel 11.0+ or 12.0+\n- RabbitMQ 3.12+\n- php-amqplib/php-amqplib ^3.6\n\n**Optional:**\n- `rabbitmq_delayed_message_exchange` plugin for delayed messages\n- `rabbitmq_prometheus` plugin for Prometheus metrics\n\n## 📦 Installation\n\n```bash\ncomposer require lettermint/laravel-rabbitmq\n```\n\nPublish the configuration file:\n\n```bash\nphp artisan vendor:publish --tag=rabbitmq-config\n```\n\nUpdate your `config/queue.php`:\n\n```php\n'connections' =\u003e [\n    'rabbitmq' =\u003e [\n        'driver' =\u003e 'rabbitmq',\n        'queue' =\u003e env('RABBITMQ_QUEUE', 'default'),\n        'exchange' =\u003e env('RABBITMQ_EXCHANGE', ''),\n    ],\n],\n\n// Set as default if desired\n'default' =\u003e env('QUEUE_CONNECTION', 'rabbitmq'),\n```\n\nAdd to your `.env`:\n\n```env\nQUEUE_CONNECTION=rabbitmq\nRABBITMQ_HOST=localhost\nRABBITMQ_PORT=5672\nRABBITMQ_USER=guest\nRABBITMQ_PASSWORD=guest\nRABBITMQ_VHOST=/\n```\n\n## 🚀 Quick Start\n\nHere's a complete example - from defining a job to processing it:\n\n### 1. Define Your Job\n\n```php\n\u003c?php\n\nnamespace App\\Jobs;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\Dispatchable;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Queue\\SerializesModels;\nuse Lettermint\\RabbitMQ\\Attributes\\ConsumesQueue;\n\n#[ConsumesQueue(\n    queue: 'emails',\n    bindings: ['notifications' =\u003e 'email.*'],  // Listens to notifications exchange\n    quorum: true,                               // High availability queue\n    retryAttempts: 3,                           // Retry up to 3 times\n)]\nclass SendEmailJob implements ShouldQueue\n{\n    use Dispatchable, InteractsWithQueue, SerializesModels;\n\n    public function __construct(\n        public string $email,\n        public string $subject,\n        public string $message,\n    ) {}\n\n    public function handle(): void\n    {\n        // Send your email\n        Mail::to($this-\u003eemail)-\u003esend(new NotificationMail($this-\u003esubject, $this-\u003emessage));\n    }\n}\n```\n\n### 2. Declare Topology\n\n```bash\n# Create the exchange, queue, and bindings in RabbitMQ\nphp artisan rabbitmq:declare\n```\n\n### 3. Dispatch \u0026 Consume\n\n```php\n// Dispatch the job (from anywhere in your app)\nSendEmailJob::dispatch('user@example.com', 'Welcome!', 'Thanks for signing up');\n```\n\n```bash\n# Start consuming (in production, run this in a container/supervisor)\nphp artisan rabbitmq:consume emails\n```\n\nThat's it! Your job will be routed through RabbitMQ and processed with automatic retries and dead letter handling.\n\n\u003e **💡 Tip:** In production, run consumers as Kubernetes Deployments or supervisor processes.\n\n## 📚 Core Concepts\n\nUnderstanding these RabbitMQ concepts will help you use this package effectively:\n\n### Exchange → Binding → Queue Flow\n\n```\n┌─────────────┐    routing key: email.welcome     ┌──────────────┐\n│   Producer  │──────────────────────────────────►│   Exchange   │\n└─────────────┘                                   │ \"notifications\"│\n                                                  └───────┬────────┘\n                                                          │ binding: email.*\n                                                          ▼\n                                                  ┌──────────────┐\n                                                  │    Queue     │\n                                                  │   \"emails\"   │\n                                                  └───────┬──────┘\n                                                          │\n                                                          ▼\n                                                  ┌──────────────┐\n                                                  │   Consumer   │\n                                                  │ (Your Job)   │\n                                                  └──────────────┘\n```\n\n- **Exchange**: Routes messages based on routing keys (like a post office)\n- **Queue**: Stores messages until consumed (like a mailbox)\n- **Binding**: Routing rule connecting exchange to queue (e.g., `email.*` matches `email.welcome`)\n- **Routing Key**: Label on each message determining which queue(s) receive it\n\n### Attribute-Based Configuration\n\nInstead of manually configuring exchanges and queues in RabbitMQ, define them with attributes:\n\n```php\n// This attribute tells the package:\n// 1. Create a queue named \"emails\"\n// 2. Create a quorum queue (HA, durable)\n// 3. Bind it to the \"notifications\" exchange with pattern \"email.*\"\n// 4. Set up DLQ with 3 retry attempts\n#[ConsumesQueue(\n    queue: 'emails',\n    bindings: ['notifications' =\u003e 'email.*'],\n    quorum: true,\n    retryAttempts: 3,\n)]\n```\n\nWhen you run `php artisan rabbitmq:declare`, the package scans your job classes and creates everything automatically.\n\n## 📖 Usage Examples\n\n### Basic Usage\n\n**Simple job with a queue:**\n\n```php\n#[ConsumesQueue(\n    queue: 'default',\n    bindings: ['tasks' =\u003e '#'],  // Catch all messages from 'tasks' exchange\n)]\nclass ProcessTaskJob implements ShouldQueue\n{\n    public function handle(): void\n    {\n        // Process the task\n    }\n}\n```\n\n**Creating an exchange** (optional - useful for organization):\n\n```php\n\u003c?php\n\nnamespace App\\RabbitMQ\\Exchanges;\n\nuse Lettermint\\RabbitMQ\\Attributes\\Exchange;\nuse Lettermint\\RabbitMQ\\Enums\\ExchangeType;\n\n#[Exchange(name: 'tasks', type: ExchangeType::Topic)]\nclass TasksExchange {}\n```\n\n### Intermediate Usage\n\n**Priority queues** for time-sensitive jobs:\n\n```php\nuse Lettermint\\RabbitMQ\\Contracts\\HasPriority;\n\n#[ConsumesQueue(\n    queue: 'urgent-tasks',\n    bindings: ['tasks' =\u003e 'urgent.*'],\n    quorum: false,        // Priority requires classic queue\n    maxPriority: 10,      // 0 = lowest, 10 = highest\n)]\nclass UrgentTaskJob implements ShouldQueue, HasPriority\n{\n    public function __construct(\n        public string $taskId,\n        public int $priority = 5,\n    ) {}\n\n    public function getPriority(): int\n    {\n        return $this-\u003epriority;\n    }\n}\n\n// Dispatch with high priority\nUrgentTaskJob::dispatch($taskId, priority: 10);\n```\n\n**Delayed/scheduled messages:**\n\n```php\n// Requires rabbitmq_delayed_message_exchange plugin\n// Enable in config/rabbitmq.php: 'delayed.enabled' =\u003e true\n\n// Delay by seconds\nSendEmailJob::dispatch($email)-\u003edelay(300);  // 5 minutes\n\n// Delay with Carbon\nSendEmailJob::dispatch($email)-\u003edelay(now()-\u003eaddHours(2));\n\n// Schedule for specific time\nSendEmailJob::dispatch($email)-\u003edelay(now()-\u003etomorrow()-\u003esetHour(9));\n```\n\n### Advanced Usage\n\n**Multiple bindings** (listen to multiple routing patterns):\n\n```php\n#[ConsumesQueue(\n    queue: 'notifications',\n    bindings: [\n        'events' =\u003e ['user.created', 'user.updated'],\n        'alerts' =\u003e 'critical.*',\n    ],\n)]\n```\n\n**Exchange-to-exchange binding** (hierarchical routing):\n\n```php\n// Parent exchange\n#[Exchange(name: 'events', type: ExchangeType::Topic)]\nclass EventsExchange {}\n\n// Child exchange bound to parent\n#[Exchange(\n    name: 'user-events',\n    type: ExchangeType::Topic,\n    bindTo: 'events',\n    bindRoutingKey: 'user.#',\n)]\nclass UserEventsExchange {}\n```\n\n**Custom retry strategy:**\n\n```php\nuse Lettermint\\RabbitMQ\\Enums\\RetryStrategy;\n\n#[ConsumesQueue(\n    queue: 'api-calls',\n    bindings: ['tasks' =\u003e 'api.*'],\n    retryAttempts: 5,\n    retryStrategy: RetryStrategy::Exponential,\n    retryDelays: [30, 60, 300, 900, 3600],  // 30s, 1m, 5m, 15m, 1h\n)]\n```\n\n**Repeatable attribute** (one job, multiple queues):\n\n```php\n// This job can be consumed from either queue\n#[ConsumesQueue(queue: 'primary', bindings: ['tasks' =\u003e 'important.*'])]\n#[ConsumesQueue(queue: 'secondary', bindings: ['tasks' =\u003e 'background.*'])]\nclass FlexibleJob implements ShouldQueue\n{\n    // ...\n}\n```\n\n## ⚙️ Configuration Reference\n\n### Environment Variables\n\n```env\n# Connection\nRABBITMQ_HOST=localhost\nRABBITMQ_PORT=5672\nRABBITMQ_USER=guest\nRABBITMQ_PASSWORD=guest\nRABBITMQ_VHOST=/\n\n# Behavior\nRABBITMQ_HEARTBEAT=60\nRABBITMQ_PREFETCH_COUNT=10\nRABBITMQ_DELAYED_ENABLED=true\n\n# Publisher\nRABBITMQ_PUBLISHER_CONFIRM=true\n```\n\n### Attribute: `#[Exchange]`\n\n```php\n#[Exchange(\n    name: 'events',                    // Required: Exchange name\n    type: ExchangeType::Topic,         // topic, direct, fanout, headers, x-delayed-message\n    durable: true,                     // Survive broker restart\n    autoDelete: false,                 // Delete when no bindings\n    internal: false,                   // Only accessible via e2e bindings\n    bindTo: 'parent-exchange',         // Parent exchange for e2e binding\n    bindRoutingKey: 'events.#',        // Routing pattern for parent\n    arguments: [],                     // Custom exchange arguments\n)]\n```\n\n**Exchange Types:**\n- `Topic`: Pattern-based routing (e.g., `user.*.created`)\n- `Direct`: Exact routing key match\n- `Fanout`: Broadcast to all bound queues\n- `Headers`: Route by message headers\n- `DelayedMessage`: Delayed delivery (requires plugin)\n\n### Attribute: `#[ConsumesQueue]`\n\n```php\n#[ConsumesQueue(\n    // Required\n    queue: 'my-queue',                           // Queue name\n\n    // Bindings\n    bindings: [                                  // Exchange =\u003e routing key(s)\n        'exchange-name' =\u003e 'routing.key',\n        'other-exchange' =\u003e ['key1', 'key2'],\n    ],\n\n    // Queue type (choose one)\n    quorum: true,                                // Quorum queue (HA, recommended)\n    maxPriority: 10,                             // Classic with priority (quorum: false)\n\n    // Limits\n    messageTtl: 86400000,                        // Message TTL in ms (24h)\n    maxLength: 1000000,                          // Max queue length\n    overflow: OverflowBehavior::RejectPublishDlx, // Overflow behavior\n\n    // Dead letter \u0026 retry\n    dlqExchange: null,                           // Custom DLQ exchange (auto-derived if null)\n    retryAttempts: 3,                            // Max retries before permanent DLQ\n    retryStrategy: RetryStrategy::Exponential,   // exponential, fixed, linear\n    retryDelays: [60, 300, 900],                 // Delays in seconds\n\n    // Consumer settings\n    prefetch: 10,                                // Messages to prefetch (QoS)\n    timeout: 30,                                 // Job timeout in seconds\n)]\n```\n\n**Important Notes:**\n- Quorum queues provide high availability but don't support priorities\n- Use classic queues (`quorum: false`) if you need `maxPriority`\n- DLQ exchange is auto-created based on your first binding exchange\n\n### Config File Options\n\nSee `config/rabbitmq.php` for full options. Key settings:\n\n```php\n// Discovery paths (where to scan for attributes)\n'discovery' =\u003e [\n    'paths' =\u003e [\n        app_path('Jobs'),\n        app_path('RabbitMQ'),\n    ],\n],\n\n// Default queue settings (for jobs without attributes)\n'queue' =\u003e [\n    'exchange' =\u003e '',  // Fallback exchange\n],\n\n// Delayed messages\n'delayed' =\u003e [\n    'enabled' =\u003e true,\n    'max_delay' =\u003e 86400000,  // 24 hours max\n],\n```\n\n## 🎮 Artisan Commands\n\n### Topology Management\n\n```bash\n# Declare all exchanges, queues, and bindings\nphp artisan rabbitmq:declare\n\n# Preview what will be created (dry run)\nphp artisan rabbitmq:declare --dry-run\n\n# View topology as tree\nphp artisan rabbitmq:topology\n\n# Export topology as JSON\nphp artisan rabbitmq:topology --format=json\n```\n\n### Queue Operations\n\n```bash\n# List all queues with stats\nphp artisan rabbitmq:queues\n\n# Include DLQ queues in list\nphp artisan rabbitmq:queues --include-dlq\n\n# Watch mode (updates every 2s)\nphp artisan rabbitmq:queues --watch\n\n# Purge a queue (delete all messages)\nphp artisan rabbitmq:purge my-queue\n```\n\n### Consumer\n\n```bash\n# Start consuming from a queue\nphp artisan rabbitmq:consume my-queue\n\n# With custom settings\nphp artisan rabbitmq:consume my-queue \\\n    --prefetch=25 \\\n    --timeout=120 \\\n    --max-jobs=500 \\\n    --max-memory=256\n\n# Stop when empty (useful for testing)\nphp artisan rabbitmq:consume my-queue --stop-when-empty\n```\n\n**Consumer Options:**\n- `--prefetch`: Messages to prefetch (default: 10)\n- `--timeout`: Job timeout in seconds (default: 60)\n- `--max-jobs`: Exit after N jobs (0 = unlimited)\n- `--max-time`: Exit after N seconds (0 = unlimited)\n- `--max-memory`: Exit if memory exceeds N MB (default: 128)\n- `--stop-when-empty`: Exit when queue is empty\n\n### Dead Letter Queue Operations\n\n```bash\n# Replay DLQ messages back to original queue\nphp artisan rabbitmq:replay-dlq my-queue\n\n# Preview replay without moving messages\nphp artisan rabbitmq:replay-dlq my-queue --dry-run\n\n# Limit number of messages to replay\nphp artisan rabbitmq:replay-dlq my-queue --limit=100\n\n# Inspect DLQ messages without removing them\nphp artisan rabbitmq:dlq-inspect my-queue\n\n# Inspect specific message\nphp artisan rabbitmq:dlq-inspect my-queue --id=message-uuid\n\n# Limit number of messages shown\nphp artisan rabbitmq:dlq-inspect my-queue --limit=20\n\n# JSON output\nphp artisan rabbitmq:dlq-inspect my-queue --format=json\n\n# Purge DLQ messages (permanently delete)\nphp artisan rabbitmq:dlq-purge my-queue\n\n# Purge specific message\nphp artisan rabbitmq:dlq-purge my-queue --id=message-uuid\n\n# Purge old messages only\nphp artisan rabbitmq:dlq-purge my-queue --older-than=7d\n\n# Preview without deleting\nphp artisan rabbitmq:dlq-purge my-queue --dry-run\n\n# Skip confirmation\nphp artisan rabbitmq:dlq-purge my-queue --force\n```\n\n### Monitoring\n\n```bash\n# Health check\nphp artisan rabbitmq:health\n\n# JSON output (for monitoring tools)\nphp artisan rabbitmq:health --json\n```\n\n## 🔄 Dead Letter Queues\n\nDLQs are automatically created for every queue to handle failed messages.\n\n### How It Works\n\n```\n┌──────────────┐\n│ Original Queue│  Job fails or times out\n│  \"emails\"    │─────────────┐\n└──────────────┘             │\n                             ▼\n                     ┌──────────────┐\n                     │  DLQ Exchange│\n                     │ \"notifications.dlq\"\n                     └───────┬──────┘\n                             │\n                             ▼\n                     ┌──────────────┐\n                     │   DLQ Queue  │  Retry after delay\n                     │ \"dlq:emails\" │─────────────┐\n                     └──────────────┘             │\n                                                  │\n         ┌────────────────────────────────────────┘\n         │\n         ▼\n┌──────────────┐\n│ Original Queue│  If retries exhausted → stays in DLQ\n│  \"emails\"    │\n└──────────────┘\n```\n\n### Retry Strategies\n\n**Exponential** (recommended for API calls):\n```php\nretryStrategy: RetryStrategy::Exponential,\nretryDelays: [60, 300, 900],  // 1m, 5m, 15m, then 15m for remaining\n```\n\n**Fixed** (same delay every time):\n```php\nretryStrategy: RetryStrategy::Fixed,\nretryDelays: [300],  // Always 5 minutes\n```\n\n**Linear** (increasing delay):\n```php\nretryStrategy: RetryStrategy::Linear,\nretryDelays: [60],  // 1m, 2m, 3m, 4m...\n```\n\n### Messages Go to DLQ When:\n\n1. Job throws unhandled exception (after retries)\n2. Job exceeds timeout\n3. Consumer rejects without requeue\n4. Queue message TTL expires\n5. Queue max-length exceeded (with `overflow: RejectPublishDlx`)\n\n## ☸️ Kubernetes Deployment\n\nDeploy workers as Kubernetes Deployments for automatic scaling and restarts.\n\n### Basic Worker Deployment\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: queue-worker-emails\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: queue-worker\n      queue: emails\n  template:\n    metadata:\n      labels:\n        app: queue-worker\n        queue: emails\n    spec:\n      containers:\n        - name: worker\n          image: your-app:latest\n          command: [\"php\", \"artisan\", \"rabbitmq:consume\", \"emails\"]\n          args:\n            - \"--prefetch=25\"\n            - \"--max-jobs=500\"\n            - \"--max-memory=256\"\n          env:\n            - name: RABBITMQ_HOST\n              value: \"rabbitmq.default.svc.cluster.local\"\n            - name: RABBITMQ_USER\n              valueFrom:\n                secretKeyRef:\n                  name: rabbitmq-credentials\n                  key: username\n            - name: RABBITMQ_PASSWORD\n              valueFrom:\n                secretKeyRef:\n                  name: rabbitmq-credentials\n                  key: password\n          resources:\n            requests:\n              memory: \"128Mi\"\n              cpu: \"100m\"\n            limits:\n              memory: \"512Mi\"\n              cpu: \"500m\"\n```\n\n### Horizontal Pod Autoscaler (HPA)\n\nScale based on queue depth using KEDA or RabbitMQ metrics:\n\n```yaml\napiVersion: autoscaling/v2\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: queue-worker-emails-hpa\nspec:\n  scaleTargetRef:\n    apiVersion: apps/v1\n    kind: Deployment\n    name: queue-worker-emails\n  minReplicas: 2\n  maxReplicas: 20\n  metrics:\n    - type: External\n      external:\n        metric:\n          name: rabbitmq_queue_messages_ready\n          selector:\n            matchLabels:\n              queue: emails\n        target:\n          type: AverageValue\n          averageValue: \"100\"  # Target: 100 messages per pod\n```\n\n### Best Practices\n\n- Set `--max-jobs` to restart workers periodically (prevents memory leaks)\n- Set `--max-memory` slightly below container limits\n- Use `livenessProbe` and `readinessProbe` for health checks\n- Run `rabbitmq:declare` in init container or CI/CD pipeline\n- Use `PodDisruptionBudget` to maintain availability during updates\n\n## 🔧 Advanced Topics\n\n### Fallback Routing for Third-Party Jobs\n\nJobs without `#[ConsumesQueue]` (e.g., from packages) use fallback routing:\n\n**Routing:** `config('rabbitmq.queue.exchange')` with key `'fallback.{queue_name}'`\n\nCreate a catch-all queue for these:\n\n```php\n#[ConsumesQueue(\n    queue: 'fallback',\n    bindings: ['your-exchange' =\u003e 'fallback.#'],\n)]\nclass FallbackJob implements ShouldQueue {}\n```\n\n### Quorum vs Classic Queues\n\n**Use Quorum Queues (default) when:**\n- You need high availability (HA)\n- Data durability is critical\n- Running in clustered RabbitMQ\n\n**Use Classic Queues when:**\n- You need message priorities\n- You need very low latency (single-node)\n- Legacy compatibility required\n\n**Cannot combine:** `quorum: true` and `maxPriority` are mutually exclusive.\n\n### Publisher Confirms\n\nPublisher confirms ensure messages reach RabbitMQ successfully. Enabled by default:\n\n```php\n'publisher' =\u003e [\n    'confirm' =\u003e true,  // Wait for RabbitMQ acknowledgment\n],\n```\n\nIf confirm fails, Laravel throws an exception and the job can be retried by your queue worker.\n\n### Heartbeats \u0026 Long-Running Jobs\n\nThe package sends heartbeats automatically during job execution to prevent connection timeouts.\n\n**For jobs longer than 2× heartbeat interval:**\n- Heartbeats work automatically with `ext-pcntl`\n- If job has `$timeout` property, heartbeats are disabled during execution (both use `SIGALRM`)\n- For long jobs needing heartbeat: set `public $timeout = 0;` on the job class\n\n## 🐛 Troubleshooting\n\n### Connection Issues\n\n**Problem:** `AMQPConnectionException: Connection refused`\n\n**Solutions:**\n- Verify RabbitMQ is running: `docker ps` or `systemctl status rabbitmq-server`\n- Check connection details in `.env` match your RabbitMQ instance\n- Ensure firewall allows port 5672\n- Test connection: `telnet rabbitmq-host 5672`\n\n### Messages Not Routing\n\n**Problem:** Messages published but not appearing in queue\n\n**Solutions:**\n- Run `php artisan rabbitmq:topology` to verify bindings\n- Check routing key matches binding pattern:\n  - `email.*` matches `email.welcome` but not `email.welcome.urgent`\n  - `email.#` matches `email.welcome.urgent`\n- Verify exchange and queue were declared: `php artisan rabbitmq:declare`\n- Check RabbitMQ management UI (port 15672) for unrouted messages\n\n### Consumer Stops Unexpectedly\n\n**Problem:** `rabbitmq:consume` exits without error\n\n**Solutions:**\n- Check memory limit: `--max-memory=256` (increase if needed)\n- Check job limit: `--max-jobs=500` (consumer exits after N jobs by design)\n- Check time limit: `--max-time=3600` (consumer exits after N seconds)\n- Review logs for connection errors or exceptions\n- Verify heartbeat settings if jobs run longer than 2× heartbeat interval\n\n### Jobs Fail Silently\n\n**Problem:** Jobs marked as processed but work not completed\n\n**Solutions:**\n- Check your job's `handle()` method for unhandled exceptions\n- Enable failed job logging: check `failed_jobs` table\n- Review RabbitMQ DLQ: `php artisan rabbitmq:dlq-inspect your-queue`\n- Add logging to job: `Log::info('Job started', ['id' =\u003e $this-\u003eid]);`\n\n### Priority Not Working\n\n**Problem:** High priority messages not processed first\n\n**Solutions:**\n- Verify `quorum: false` (quorum queues don't support priority)\n- Verify `maxPriority` is set on queue attribute\n- Ensure job implements `HasPriority` interface\n- Check messages have priority set before prefetched messages processed\n\n### Delayed Messages Not Working\n\n**Problem:** `-\u003edelay()` doesn't delay message\n\n**Solutions:**\n- Install plugin: `rabbitmq-plugins enable rabbitmq_delayed_message_exchange`\n- Verify enabled in config: `'delayed.enabled' =\u003e true`\n- Run `php artisan rabbitmq:declare` to create delayed exchange\n- Check delay is within max: default 24 hours (`delayed.max_delay`)\n\n### High Memory Usage\n\n**Problem:** Worker memory grows over time\n\n**Solutions:**\n- Set `--max-memory=256` to restart worker before OOM\n- Set `--max-jobs=500` to periodically restart workers\n- Check for memory leaks in job code\n- Ensure job releases large objects: `unset($largeVariable);`\n- Use `--max-time=3600` for time-based restarts\n\n## 🤝 Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n## 📄 License\n\nMIT License. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flettermint%2Flaravel-rabbitmq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flettermint%2Flaravel-rabbitmq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flettermint%2Flaravel-rabbitmq/lists"}