{"id":25519711,"url":"https://github.com/aligent/magento-async-events","last_synced_at":"2025-10-12T03:03:03.662Z","repository":{"id":38270050,"uuid":"435294959","full_name":"aligent/magento-async-events","owner":"aligent","description":"Magento Webhooks, Asynchronous Events","archived":false,"fork":false,"pushed_at":"2024-06-29T03:40:30.000Z","size":786,"stargazers_count":26,"open_issues_count":1,"forks_count":4,"subscribers_count":8,"default_branch":"3.x","last_synced_at":"2025-04-02T23:46:08.430Z","etag":null,"topics":["asynchronous","events","magento","magento2","webhooks"],"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/aligent.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2021-12-05T22:33:56.000Z","updated_at":"2025-03-28T17:07:45.000Z","dependencies_parsed_at":"2024-06-19T02:54:03.270Z","dependency_job_id":"f26f27e2-d8bf-489c-8195-80f669f782e2","html_url":"https://github.com/aligent/magento-async-events","commit_stats":{"total_commits":260,"total_committers":7,"mean_commits":"37.142857142857146","dds":"0.39230769230769236","last_synced_commit":"c119db917ec391fc76ccb665a6f2e9c337205d62"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aligent%2Fmagento-async-events","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aligent%2Fmagento-async-events/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aligent%2Fmagento-async-events/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aligent%2Fmagento-async-events/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aligent","download_url":"https://codeload.github.com/aligent/magento-async-events/tar.gz/refs/heads/3.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248322773,"owners_count":21084336,"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":["asynchronous","events","magento","magento2","webhooks"],"created_at":"2025-02-19T17:29:28.298Z","updated_at":"2025-10-12T03:02:58.622Z","avatar_url":"https://github.com/aligent.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Magento Asynchronous Events\n\n[![Integration Test](https://github.com/aligent/magento-async-events/actions/workflows/integration-tests.yml/badge.svg)](https://github.com/aligent/magento-async-events/actions/workflows/integration-tests.yml)\n[![REST](https://github.com/aligent/magento-async-events/actions/workflows/api-functional-tests.yml/badge.svg)](https://github.com/aligent/magento-async-events/actions/workflows/api-functional-tests.yml)\n\nA framework for reliably handling asynchronous events with Magento.\n\n* **Asynchronous**: The module uses RabbitMQ (or DB queues) to leverage asynchronous message delivery.\n* **Flexible**: Decoupling events and dispatches provide greater flexibility in message modelling.\n* **Scalable**: Handles back pressure and provides an asynchronous failover model automatically.\n\n## Support\n\n| Async Events | Magento 2.3.x      | \u003e= Magento 2.4.0 \u003c= Magento 2.4.3 | \u003e= Magento 2.4.4   |\n|--------------|--------------------|-----------------------------------|--------------------|\n| 2.x          | :white_check_mark: | :white_check_mark:                | :x:                |\n| 3.x          | :x:                | :x:                               | :white_check_mark: |\n\n## Installation\n\n```\ncomposer require aligent/async-events\n```\n\n## Usage\n\n### Define an asynchronous event\n\nCreate a new `async_events.xml` under a module's `etc/` directory.\n\n```xml\n\u003c?xml version=\"1.0\"?\u003e\n\u003cconfig\n    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n    xsi:noNamespaceSchemaLocation=\"urn:magento:module:Aligent_AsyncEvents:etc/async_events.xsd\"\n\u003e\n    \u003casync_event name=\"sales.order.created\"\u003e\n        \u003cservice class=\"Magento\\Sales\\Api\\OrderRepositoryInterface\" method=\"get\"/\u003e\n    \u003c/async_event\u003e\n\u003c/config\u003e\n```\n\n### Create Subscription\n\n#### HTTP Subscription\n```shell\ncurl --location --request POST 'https://m2.dev.aligent.consulting:44356/rest/V1/async_event' \\\n--header 'Authorization: Bearer TOKEN' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n    \"asyncEvent\": {\n        \"event_name\": \"sales.order.created\",\n        \"recipient_url\": \"https://example.com/order_created\",\n        \"verification_token\": \"fD03@NpYbXYg\",\n        \"metadata\": \"http\"\n    }\n}'\n```\n\n#### Amazon EventBridge Subscription\nRequires the [EventBridge Notifier](https://github.com/aligent/magento2-eventbridge-notifier)\n\n```shell\ncurl --location --request POST 'https://m2.dev.aligent.consulting:44356/rest/V1/async_event' \\\n--header 'Authorization: Bearer TOKEN' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n    \"asyncEvent\": {\n        \"event_name\": \"sales.order.created\",\n        \"recipient_url\": \"arn:aws:events:ap-southeast-2:005158166381:rule/Test.EventBridge.Rule\",\n        \"verification_token\": \"aIW0G9n3*9wN\",\n        \"metadata\": \"event_bridge\"\n    }\n}'\n```\n\n### Dispatch an asynchronous event\n```php\npublic function execute(Observer $observer): void\n{\n    /** @var Order $object */\n    $object = $observer-\u003egetEvent()-\u003egetData('order');\n\n    // arguments are the inputs required by the service class in the asynchronous\n    // event definition in async_events.xml\n    // e.g: Magento\\Sales\\Api\\OrderRepositoryInterface::get\n    $arguments = ['id' =\u003e $object-\u003egetId()];\n    $data = ['sales.order.created', $this-\u003ejson-\u003eserialize($arguments)];\n\n    $this-\u003epublisher-\u003epublish(\n        QueueMetadataInterface::EVENT_QUEUE,\n        $data\n    );\n}\n```\n\nEnsure the following consumers are running\n\n```shell\nbin/magento queue:consumer:start event.trigger.consumer\nbin/magento queue:consumer:start event.retry.consumer\n```\n\n## Advanced Usage\nRefer to the [Wiki](https://github.com/aligent/magento-async-events/wiki)\n\n\n# Features\n\n## Trace\n\nAll events are logged at the individual subscription level with a UUID.\n\nAll information from the first delivery attempt to the latest attempt is presented as a trace table. The event payload\nis also available to view for investigation purposes.\n\n![Event Trace Page](docs/trace.png)\n\n## Retries\n\nEvents are automatically retried with exponential back off. The default retry limit is 5. The maximum backoff is\n60 seconds.\n\nThe exponential backoff is calculated as `min(60, pow($deathCount, 2));`\n\n| Attempt | Backoff     |\n|---------|-------------|\n| 1       | 1 second    |\n| 2       | 4 seconds   |\n| 3       | 9 seconds   |\n| 4       | 16 seconds  |\n| 5       | 25 seconds  |\n\nTo change the default retry limit visit Admin \u003e Stores \u003e Settings \u003e Configuration \u003e Advanced \u003e System \u003e Async Events and update `Maximum Deaths`.\n\n![Retry Limit Config Page](docs/retry_limit_config.png)\n\n## Replays\n\nAn event can be replayed independent of its status. This is useful to debug or replay an event when all retries are\nexhausted.\n\nReplays start a new chain of delivery attempts and will respect the same retry mechanism if they fail again.\n\n## Lucene Query Syntax\n\nAll events are indexed in Elasticsearch by default. This allows you to search through events including the event payload!\n\nThe module supports [Lucene Query Syntax](https://lucene.apache.org/core/2_9_4/queryparsersyntax.html) to query event data like attributes.\n\nThe following attributes are available across all asynchronous events.\n\n```\nlog_id\nuuid\nevent_name\nsuccess\ncreated\n```\nThe following attributes differ between asynchronous event types.\n```\ndata\n```\n\n### Examples\n\nAssuming you have the following events configured\n```\ncustomer.created\ncustomer.updated\ncustomer.deleted\nsales.order.created\nsales.invoice.created\nshipment.created\nshipment.updated\nshipment.deleted\n```\nYou can query all customer events by using a wildcard like `event_name: customer.*` which matches the following events\n```\ncustomer.created\ncustomer.updated\ncustomer.deleted\n```\n\nYou can query all created events like `*.created` which matches the following events\n```\ncustomer.created\nsales.order.created\nsales.invoice.created\nshipment.created\n```\n\nYou can further narrow down using the other available attributes such as status or uuid.\n\nThe following query returns all customer events which have failed. `customer.* AND success: false`\n\nYou can combine complex lucene queries to fetch event history and then export them via the admin grid as a csv if you wish.\n\n#### Searching inside event payloads\nSearching an event payload depends on what event you are searching on.\n\nFor the following example event payload, four properties are indexed as attributes. Therefore, you can query on\n`data.customer_email`, `data.customer_firstname`, `data.customer_lastname` and `data.increment_id`.\nProperties inside array at any level are not searchable.\n\n```json\n{\n    \"data\": {\n        \"customer_email\": \"roni_cost@example.com\",\n        \"customer_firstname\": \"Veronica\",\n        \"customer_lastname\": \"Costello\",\n        \"increment_id\": \"CK00000001\",\n        \"payment_additional_info\": [\n            {\n                \"key\": \"method_title\",\n                \"value\": \"Check / Money order\"\n            }\n        ]\n    }\n}\n```\n\nSearch all events where the customer email is `roni_cost@example.com`\n\n`data.data.customer_email: roni_cost@example.com`\n\n![Lucene Example 1](docs/lucene_example_1.png)\n\nSearch all events with the order increment id starting with `CK` and status success\n\n`data.data.increment_id: CK* AND success: true`\n\n![Lucene Example 2](docs/lucene_example_2.png)\n\nTo turn off asynchronous event indexing visit Admin \u003e Stores \u003e Settings \u003e Configuration \u003e Advanced \u003e System \u003e\nAsync Events and disable `Enable Asynchronous Events Indexing`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faligent%2Fmagento-async-events","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faligent%2Fmagento-async-events","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faligent%2Fmagento-async-events/lists"}