{"id":26713719,"url":"https://github.com/ody-dev/amqp","last_synced_at":"2025-03-27T12:30:02.820Z","repository":{"id":284617204,"uuid":"955506445","full_name":"ody-dev/amqp","owner":"ody-dev","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-26T19:58:13.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-26T20:24:57.504Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ody-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2025-03-26T18:40:58.000Z","updated_at":"2025-03-26T19:58:16.000Z","dependencies_parsed_at":"2025-03-26T20:35:13.716Z","dependency_job_id":null,"html_url":"https://github.com/ody-dev/amqp","commit_stats":null,"previous_names":["ody-dev/amqp"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ody-dev%2Famqp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ody-dev%2Famqp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ody-dev%2Famqp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ody-dev%2Famqp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ody-dev","download_url":"https://codeload.github.com/ody-dev/amqp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245844557,"owners_count":20681734,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":"2025-03-27T12:30:02.216Z","updated_at":"2025-03-27T12:30:02.810Z","avatar_url":"https://github.com/ody-dev.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RabbitMQ Integration for ODY Framework\n\nThis package provides RabbitMQ integration for the ODY framework, allowing you to easily implement asynchronous\nmessaging patterns in your application.\n\n## Installation\n\n```bash\ncomposer require ody/amqp\n```\n\n## Configuration\n\nFirst, publish the configuration file:\n\n```bash\nphp ody publish ody/amqp\n```\n\nThis will create a `config/amqp.php` file where you can configure your RabbitMQ connections:\n\n```php\nreturn [\n    'enable' =\u003e true,\n    \n    'default' =\u003e [\n        'host' =\u003e env('RABBITMQ_HOST', 'localhost'),\n        'port' =\u003e env('RABBITMQ_PORT', 5672),\n        'user' =\u003e env('RABBITMQ_USER', 'guest'),\n        'password' =\u003e env('RABBITMQ_PASSWORD', 'guest'),\n        'vhost' =\u003e env('RABBITMQ_VHOST', '/'),\n        \n        'concurrent' =\u003e [\n            'limit' =\u003e 10,  // Max concurrent consumers per process\n        ],\n        \n        'pool' =\u003e [\n            'connections' =\u003e 5,  // Number of connections per worker\n        ],\n        \n        'params' =\u003e [\n            'connection_timeout' =\u003e 3.0,\n            'read_write_timeout' =\u003e 3.0,\n            'heartbeat' =\u003e 60,\n            'keepalive' =\u003e true,\n        ],\n    ],\n    \n    // You can define multiple connection pools\n    'analytics' =\u003e [\n        'host' =\u003e 'analytics-rabbitmq',\n        // Other connection settings\n    ],\n    \n    'producer' =\u003e [\n        'paths' =\u003e ['app/Producers'],\n        'retry' =\u003e [\n            'max_attempts' =\u003e 3,\n            'initial_interval' =\u003e 1000,  // ms\n            'multiplier' =\u003e 2.0,\n            'max_interval' =\u003e 10000,  // ms\n        ],\n    ],\n    \n    'consumer' =\u003e [\n        'paths' =\u003e ['app/Consumers'],\n        'prefetch_count' =\u003e 10,\n        'auto_declare' =\u003e true,\n    ],\n    \n    'process' =\u003e [\n        'enable' =\u003e true,\n        'max_consumers' =\u003e 10,\n        'auto_restart' =\u003e true,\n    ]\n];\n```\n\n## Setting Up Docker\n\nFor local development, you can use Docker to run RabbitMQ:\n\n```bash\ndocker run -d --name rabbitmq \\\n  -p 5672:5672 \\\n  -p 15672:15672 \\\n  -e RABBITMQ_DEFAULT_USER=admin \\\n  -e RABBITMQ_DEFAULT_PASS=password \\\n  rabbitmq:3-management\n```\n\nOr use docker-compose:\n\n```yaml\nversion: '3.8'\n\nservices:\n  rabbitmq:\n    image: rabbitmq:3-management\n    container_name: rabbitmq\n    ports:\n      - \"5672:5672\"   # AMQP protocol port\n      - \"15672:15672\" # Management UI port\n    environment:\n      - RABBITMQ_DEFAULT_USER=admin\n      - RABBITMQ_DEFAULT_PASS=password\n    volumes:\n      - rabbitmq_data:/var/lib/rabbitmq\n      - rabbitmq_log:/var/log/rabbitmq\n\nvolumes:\n  rabbitmq_data:\n  rabbitmq_log:\n```\n\n## Creating Producers\n\nProducers send messages to RabbitMQ. Create a producer class in your `app/Producers` directory:\n\n```php\n\u003c?php\n\nnamespace App\\Producers;\n\nuse Ody\\AMQP\\Attributes\\Producer;\nuse Ody\\AMQP\\Message\\ProducerMessage;\n\n#[Producer(exchange: 'user_events', routingKey: 'user.created', type: 'topic')]\nclass UserCreatedProducer extends ProducerMessage\n{\n    public function __construct(\n        private int $userId,\n        private string $email,\n        private string $username\n    ) {\n        $this-\u003epayload = [\n            'user_id' =\u003e $this-\u003euserId,\n            'email' =\u003e $this-\u003eemail,\n            'username' =\u003e $this-\u003eusername,\n            'created_at' =\u003e date('Y-m-d H:i:s')\n        ];\n    }\n}\n```\n\n## Creating Consumers\n\nConsumers receive and process messages from RabbitMQ. Create a consumer class in your `app/Consumers` directory:\n\n```php\n\u003c?php\n\nnamespace App\\Consumers;\n\nuse Ody\\AMQP\\Attributes\\Consumer;\nuse Ody\\AMQP\\Message\\ConsumerMessage;\nuse Ody\\AMQP\\Message\\Result;\nuse PhpAmqpLib\\Message\\AMQPMessage;\n\n#[Consumer(\n    exchange: 'user_events',\n    routingKey: 'user.created',\n    queue: 'welcome_email_queue',\n    type: 'topic'\n)]\nclass WelcomeEmailConsumer extends ConsumerMessage\n{\n    public function consumeMessage(array $data, AMQPMessage $message): Result\n    {\n        try {\n            // Process the message\n            $userId = $data['user_id'];\n            $email = $data['email'];\n            $username = $data['username'];\n            \n            // Send welcome email\n            // $this-\u003eemailService-\u003esendWelcomeEmail($email, $username);\n            \n            // Log success\n            error_log(\"Welcome email sent to $email for user $userId\");\n            \n            // Acknowledge the message\n            return Result::ACK;\n        } catch (\\Exception $e) {\n            // Log the error\n            error_log(\"Failed to send welcome email: \" . $e-\u003egetMessage());\n            \n            // Reject and requeue the message for retry\n            return Result::REQUEUE;\n        }\n    }\n}\n```\n\n## Publishing Messages\n\nTo publish messages in your application code:\n\n```php\nuse Ody\\AMQP\\AMQP;\nuse App\\Producers\\UserCreatedProducer;\n\n// In your controller or service\npublic function registerUser(array $userData)\n{\n    // Create user in database\n    $user = $this-\u003euserRepository-\u003ecreate($userData);\n    \n    // Publish event\n    AMQP::publish(UserCreatedProducer::class, [\n        $user-\u003eid,              // userId\n        $user-\u003eemail,           // email\n        $user-\u003eusername         // username\n    ]);\n    \n    return $user;\n}\n```\n\n## Delayed Messages\n\nYou can publish messages with a delay:\n\n```php\n// Send a reminder after 24 hours\nAMQP::publishDelayed(ReminderProducer::class, [\n    $user-\u003eid,\n    'Your trial is about to expire'\n], 86400000); // 24 hours in milliseconds\n```\n\n## Working with Topic Exchanges\n\nTopic exchanges provide flexible routing:\n\n```php\n// Producer\n#[Producer(exchange: 'notifications', routingKey: 'user.123.email', type: 'topic')]\nclass UserNotificationProducer extends ProducerMessage { /* ... */ }\n\n// Consumer with wildcards\n#[Consumer(\n    exchange: 'notifications',\n    routingKey: 'user.*.email',  // Match any user ID\n    queue: 'email_notifications',\n    type: 'topic'\n)]\nclass EmailNotificationConsumer extends ConsumerMessage { /* ... */ }\n```\n\n## Message Results\n\nConsumers should return one of these results:\n\n- `Result::ACK`: Acknowledge the message (successfully processed)\n- `Result::NACK`: Negative acknowledgment (failed to process, don't requeue)\n- `Result::REQUEUE`: Reject and requeue the message (retry later)\n- `Result::DROP`: Reject the message and drop it (don't retry)\n\n```php\npublic function consumeMessage(array $data, AMQPMessage $message): Result\n{\n    try {\n        // Process message\n        return Result::ACK;\n    } catch (\\Exception $e) {\n        // Decide based on error type\n        if ($e instanceof TemporaryFailureException) {\n            return Result::REQUEUE;  // Retry later\n        }\n        \n        // Permanent failure\n        return Result::DROP;  // Don't retry\n    }\n}\n```\n\n## Monitoring and Management\n\nRabbitMQ provides a management UI available at `http://localhost:15672/` (default username/password is the one you\nconfigured).\n\nYou can use this interface to:\n\n- Monitor queues and exchanges\n- View message rates and consumer activity\n- Manage exchanges, queues, and bindings\n- View connections and channels\n\n## Troubleshooting\n\n### Common Issues\n\n1. **Connection Refused**: Check your RabbitMQ server is running and the connection details are correct.\n2. **Exchange/Queue Not Found**: Verify exchange and queue names match between producers and consumers.\n3. **Type Mismatch**: Ensure exchange types match between producers and consumers (e.g., 'topic', 'direct', 'fanout').\n4. **Messages Not Being Consumed**: Check that consumers are running and bound to the correct exchange and routing key.\n\n### Debugging\n\nEnable detailed logging in your consumers:\n\n```php\npublic function consumeMessage(array $data, AMQPMessage $message): Result\n{\n    error_log(\"Received message: \" . json_encode($data));\n    error_log(\"Delivery tag: \" . $message-\u003egetDeliveryTag());\n    // Rest of your processing\n}\n```\n\n## Best Practices\n\n1. **Use Topic Exchanges**: They provide more flexibility than direct exchanges.\n2. **Implement Error Handling**: Always handle exceptions in consumers and return appropriate result codes.\n3. **Consider Message Idempotency**: Design your consumers to handle duplicate messages safely.\n4. **Set Appropriate Prefetch Count**: Adjust based on your processing speed and resource constraints.\n5. **Monitor Queue Lengths**: Long queues may indicate processing bottlenecks.\n6. **Use Descriptive Routing Keys**: Follow a convention like `entity.action.type` for better organization.\n\n## Next Steps\n\n- Implement dead letter exchanges for failed messages\n- Set up message TTL (time-to-live) for expiring old messages\n- Implement circuit breakers for external service calls\n- Add message batching for better performance\n- Set up message priorities for critical messages\n\n---\n\nFor more advanced usage and configuration options, refer to the full documentation or explore\nthe [RabbitMQ official documentation](https://www.rabbitmq.com/documentation.html).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fody-dev%2Famqp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fody-dev%2Famqp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fody-dev%2Famqp/lists"}