PHPackages                             magetips/module-azure - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Queues &amp; Workers](/categories/queues)
4. /
5. magetips/module-azure

ActiveMagento2-module[Queues &amp; Workers](/categories/queues)

magetips/module-azure
=====================

Azure Service Bus integration for Magento's MessageQueue framework, built for Dynamics 365 connectivity.

v1.0.0(1mo ago)00GPL-3.0-or-laterPHPPHP ^8.1

Since Jul 3Pushed 1mo agoCompare

[ Source](https://github.com/mage-tips/azure)[ Packagist](https://packagist.org/packages/magetips/module-azure)[ RSS](/packages/magetips-module-azure/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (8)Versions (2)Used By (0)

   title README  MageTips\_Azure
===============

[](#magetips_azure)

Connects Magento's native MessageQueue framework to **Azure Service Bus**, so publishers, consumers, and topology declared via the standard `communication.xml` / `queue_topology.xml` / `queue_publisher.xml` / `queue_consumer.xml` config work against an Azure Service Bus namespace exactly the way they would against RabbitMQ — same XML, same `PublisherInterface`/consumer handler signatures, same `bin/magento queue:consumers:start`.

Built on [`magetips/windowsazure`](https://github.com/mage-tips/windowsazure), a maintained fork of the archived Azure PHP SDK, trimmed to only the Service Bus REST client this module needs.

Table of contents
-----------------

[](#table-of-contents)

- [Installation](#installation)
- [Core concept: how Magento's MQ abstractions map to Azure](#core-concept-how-magentos-mq-abstractions-map-to-azure)
- [Quick start](#quick-start)
- [Declaring a topic: the four files you need](#declaring-a-topic-the-four-files-you-need)
- [Publishing and consuming](#publishing-and-consuming)
- [Extending topology](#extending-topology)
    - [Multi-subscription fan-out](#multi-subscription-fan-out)
    - [Synchronous / RPC topics](#synchronous--rpc-topics)
- [Topology installation (setup:upgrade)](#topology-installation-setupupgrade)
- [Running consumers](#running-consumers)
- [Configuration reference](#configuration-reference)
- [Dead-lettering](#dead-lettering)
- [Message log, archiving, and cleanup](#message-log-archiving-and-cleanup)
- [Admin UI reference](#admin-ui-reference)
- [CLI command reference](#cli-command-reference)
- [Logging](#logging)
- [Cron jobs](#cron-jobs)
- [Key classes](#key-classes)
- [Known limitations](#known-limitations)
- [License](#license)

Installation
------------

[](#installation)

```
composer require magetips/module-azure
bin/magento module:enable MageTips_Azure
bin/magento setup:upgrade
```

`magetips/module-azure` requires [`magetips/windowsazure`](https://github.com/mage-tips/windowsazure)(the underlying Service Bus REST client) as a normal Composer dependency, so it's pulled in automatically by the command above — no separate install step.

If Composer can't resolve `magetips/windowsazure` (for example, it isn't registered on Packagist yet), add it as a VCS repository in your project's root `composer.json` and re-run `composer require`:

```
{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/mage-tips/windowsazure"
        }
    ]
}
```

Core concept: how Magento's MQ abstractions map to Azure
--------------------------------------------------------

[](#core-concept-how-magentos-mq-abstractions-map-to-azure)

Magento's MessageQueue framework was designed around AMQP (RabbitMQ), so its vocabulary is exchanges, queues, and bindings. Azure Service Bus has its own model — topics and subscriptions. This module bridges the two:

Magento concept (XML)Azure Service Bus conceptNotes`communication.xml` ``Azure **Topic**The thing you publish to.`queue_topology.xml` ``Azure **Topic** (again)In this module's convention, exchange name == topic name.`queue_topology.xml` ``Azure **Subscription**Each binding under an exchange becomes one Azure subscription on that topic. One binding = the common case; more than one = [fan-out](#multi-subscription-fan-out).`queue_consumer.xml` ``A consumer reading one SubscriptionThe `queue` attribute must match a binding's `destination`.Admin **Service Bus Configurations** grid rowNamespace host + SAS credentials + default subscription name, keyed by topicSee [Configuration reference](#configuration-reference).The practical upshot: **one topic can have several independent subscriptions**, each getting its own full copy of every message (Azure's native fan-out) — this module supports that directly, see [Multi-subscription fan-out](#multi-subscription-fan-out).

Quick start
-----------

[](#quick-start)

1. Install the module — see [Installation](#installation).
2. Declare a topic across `communication.xml`, `queue_topology.xml`, `queue_publisher.xml`, and `queue_consumer.xml` in your own module — see [Declaring a topic](#declaring-a-topic-the-four-files-you-need)below for the exact shape each file needs.
3. Go to **Stores &gt; Configuration &gt; MageTips &gt; Azure Service Bus &gt; Service Bus Configurations** and add a row for your topic with your Azure Service Bus namespace host, a SAS **Access Key** name/secret, and a subscription name.
4. Either enable **Topology &gt; Automatically Create Topics on setup:upgrade** and re-run `setup:upgrade`, or create the topic/subscription yourself in the Azure Portal.
5. Publish via the standard `PublisherInterface::publish($topicName, $data)` and consume with `bin/magento queue:consumers:start `.
6. Check **Azure Service Bus &gt; Message Log** in the admin, or `var/log/azure_service_bus.log`.

Declaring a topic: the four files you need
------------------------------------------

[](#declaring-a-topic-the-four-files-you-need)

Every topic touches four config files, each answering a different question. This is the part new developers usually trip over, so here's a complete example — a fictional `vendor_module.order_export` topic — file by file, in the order Magento actually needs them.

### 1. `communication.xml` — "what does this topic carry, and who handles it?"

[](#1-communicationxml--what-does-this-topic-carry-and-who-handles-it)

```

```

- `name` — the topic name. This is the string every other file below references.
- `request` — the PHP type of the message payload (`string`, `int`, a DTO/API interface, etc.).
- `response` + `is_synchronous="true"` — only needed for [RPC topics](#synchronous--rpc-topics).
- `` — which class/method actually processes a decoded message. You can register more than one handler per topic; Magento calls all of them.

### 2. `queue_topology.xml` — "what does this topic look like on the transport?"

[](#2-queue_topologyxml--what-does-this-topic-look-like-on-the-transport)

```

```

- `` — becomes the Azure **Topic**. Must equal the `communication.xml` topic name.
- `connection="azure-servicebus"` — always this literal value for anything this module should handle (it's how `MageTips\Azure\MessageQueue\ConnectionTypeResolver` claims the connection).
- `` — becomes an Azure **Subscription** name (unless it differs from the topic name, see [fan-out](#multi-subscription-fan-out)). In the common case, `destination` equals the topic name, exactly like above.

### 3. `queue_publisher.xml` — "which connection/exchange does publishing this topic use?"

[](#3-queue_publisherxml--which-connectionexchange-does-publishing-this-topic-use)

```

```

- `topic` — again, must match. `exchange` — must match the `` from `queue_topology.xml`. This file is what `Magento\Framework\MessageQueue\PublisherInterface::publish()` reads to route a topic to the right transport.

### 4. `queue_consumer.xml` — "who reads which subscription, and how?"

[](#4-queue_consumerxml--who-reads-which-subscription-and-how)

```

```

- `name` — the consumer name you pass to `bin/magento queue:consumers:start `.
- `queue` — must match a binding's `destination` from `queue_topology.xml` (**not** necessarily the topic name — see fan-out below).
- `consumerInstance` — always `MageTips\Azure\Queue\MessageQueueConsumer` for this module. Don't write your own; it's what wires Azure-specific logging, dead-lettering, and lock-renewal into the generic consumer contract.
- `handler` — `Class::method`, invoked with the decoded message.

Optional per-consumer tuning attributes (same as any Magento consumer, nothing Azure-specific): `maxMessages`, `sleep` (seconds between polls when idle), `maxIdleTime`, `onlySpawnWhenMessageAvailable`.

### The naming rule that ties it all together

[](#the-naming-rule-that-ties-it-all-together)

FileAttributeMust equal`communication.xml```the topic name everywhere else`queue_topology.xml```the topic name`queue_topology.xml```the topic name`queue_topology.xml```the Azure subscription (see fan-out for when this differs from the topic name)`queue_publisher.xml```the topic name`queue_publisher.xml```the `` above`queue_consumer.xml```a `` aboveGet any of these out of sync and Magento's own config validation (or `TopologyInstaller`) will fail loudly at `setup:upgrade` time, not silently at runtime.

Publishing and consuming
------------------------

[](#publishing-and-consuming)

Publishing uses the plain Magento API — nothing Azure-specific in your calling code:

```
/** @var \Magento\Framework\MessageQueue\PublisherInterface $publisher */
$publisher->publish('vendor_module.order_export', json_encode(['orderId' => 12345]));
```

A consumer handler is a plain class/method, also nothing Azure-specific:

```
namespace Vendor\Module\Queue\Consumer;

class OrderExportConsumer
{
    public function process(string $message): void
    {
        $data = json_decode($message, true);
        // ... do the work ...
    }
}
```

Everything Azure-specific — connecting, encoding, peek-lock receive, ack/reject, dead-lettering, logging — happens inside `MageTips\Azure\Queue\MessageQueueConsumer` and `MessageQueue\Queue`/`Exchange`, which `consumerInstance="MageTips\Azure\Queue\MessageQueueConsumer"` wires in for you.

Extending topology
------------------

[](#extending-topology)

### Multi-subscription fan-out

[](#multi-subscription-fan-out)

Azure Service Bus topics natively support more than one independent subscription — each subscription gets its own copy of every message published to the topic, the same way a RabbitMQ topic exchange can bind to multiple queues. Add a second `` with a different `destination` and a matching ``:

```

```

```

```

`TopologyInstaller` creates one Azure subscription per binding under the topic. The subscription name for each binding is resolved as follows:

- If the binding's `destination` matches the topic name (the single-binding case every topic starts as), the subscription name comes from the admin-configured **Subscription** field for that topic — existing single-binding topics are completely unaffected by this feature.
- Otherwise (an additional fan-out binding), the subscription name is the binding's own `destination` — there's no separate admin config for it, the same way AMQP has no separate "friendly queue name" either.

The [Dead Letters admin page and CLI](#dead-lettering) automatically iterate every subscription on a topic, so fan-out topics don't need any special handling there either.

### Synchronous / RPC topics

[](#synchronous--rpc-topics)

`communication.xml`'s `is_synchronous="true"` topics are fully supported: `MessageQueue\Exchange::enqueue()`publishes the request, then polls the reply queue (Azure has no blocking wait like AMQP's `channel->wait()`, but `ReceiveMessageOptions::setTimeout()` maps to Azure's own server-side long-poll, so this isn't a client busy-loop) matching on `correlation_id`, and returns the reply body — or throws a `LocalizedException` after 30 seconds if nothing matching arrives (mirrors `Magento\Framework\Amqp\Exchange::RPC_CONNECTION_TIMEOUT`).

Two extra declarations are required, since Azure has no "raw queue" concept outside topic+subscription:

1. **A reply topic.** `Magento\Framework\MessageQueue\Rpc\ResponseQueueNameBuilder` builds the reply queue name as `responseQueue.`, shared by every RPC call to that topic. It needs its own ``/`` in `queue_topology.xml` (same pattern as any other topic) **and** its own `` in `communication.xml` (no handler needed — nothing consumes it via `queue_consumer.xml`, it's read directly by `Exchange::enqueue()`'s wait loop; Magento's own topology config reader validates every binding's topic against `communication.xml` regardless of whether anything consumes it).
2. **Its own admin config row** under **Service Bus Configurations**, same as the request topic — it has no fallback to another topic's credentials.

```

```

```

```

Publishing is the same `PublisherInterface::publish()` call — for a synchronous topic it blocks and returns the reply:

```
$reply = $publisher->publish('my.rpc.topic', $requestPayload); // blocks until reply or 30s timeout
```

This also requires `Magento\Framework\MessageQueue\Rpc\Publisher` wired under `PublisherPool`'s `sync` mode for the `azure-servicebus` connection type — already done in this module's `etc/di.xml`, nothing to add yourself:

```

                Magento\Framework\MessageQueue\Rpc\Publisher

```

The publishing process is the one waiting for the reply, not the one producing it, so a consumer for the topic must already be running (`bin/magento queue:consumers:start `) before you publish.

Topology installation (setup:upgrade)
-------------------------------------

[](#topology-installation-setupupgrade)

Declaring a topic in the four files above doesn't create anything on Azure by itself — something has to call `TopologyInstaller::install()`.

This is controlled by a single admin setting: **Stores &gt; Configuration &gt; MageTips &gt; Azure Service Bus &gt; Topology &gt; Automatically Create Topics on setup:upgrade** (disabled by default). It's the sole authority over this behavior — there's no separate deployment-mode check baked into the module.

- **Enabled**: `MageTips\Azure\Setup\Recurring` runs `TopologyInstaller::install()` automatically on every `bin/magento setup:upgrade`, creating any topic/subscription/rule declared in `queue_topology.xml` that doesn't already exist. Convenient for local/sandbox development — declare a topic, run `setup:upgrade`, it's on Azure. If installation fails (e.g. credentials without "Manage" rights), the failure is written to `var/log/azure_service_bus.log` and never blocks `setup:upgrade`.
- **Disabled** (default): automatic installation is a no-op. Topology is expected to be provisioned out-of-band by whoever owns Azure infrastructure (DevOps/IaC — Terraform, ARM templates, or the Portal), typically issuing **scoped, least-privilege, per-topic SAS credentials** (e.g. Send-only or Listen-only on one specific topic) rather than a namespace-wide `RootManageSharedAccessKey`.

There is deliberately no separate CLI command to trigger this manually — `Magento_Amqp` doesn't have one either, so `setup:upgrade` (with the setting enabled) is the one and only way topology gets installed, matching RabbitMQ's own behavior exactly.

If you want topology installation restricted by Magento's deployment mode (e.g. never even attempt it in production regardless of the admin setting), that's deliberately not built into this module — add a plugin or `di.xml` preference around `MageTips\Azure\System\TopologyConfig::isAutoInstallEnabled()` in your own module instead, rather than relying on logic buried in this one.

**Limitation:** with the setting left at its default (disabled), a fresh deployment against a brand-new Azure namespace will not work out of the box purely by running `setup:upgrade` — someone has to either enable the setting and run `setup:upgrade` (with sufficiently-privileged credentials), or provision the topics out-of-band (DevOps/IaC).

Running consumers
-----------------

[](#running-consumers)

This module doesn't ship its own cron or consumer-scheduling config — consumers declared in `queue_consumer.xml` are picked up and run automatically by Magento's own built-in `Magento\MessageQueue\Model\Cron\ConsumersRunner` (the `consumers_runner` cron job in `Magento_MessageQueue`), exactly the same way RabbitMQ consumers are. That runner already handles connection resolution (via `ConnectionTypeResolver`, which this module implements so it's only claimed for `azure-servicebus`connections), lock-based de-duplication, and message-availability checks before spawning a process.

Configure it the standard Magento way, in `app/etc/env.php`:

```
'cron_consumers_runner' => [
    'cron_run' => true,
    'max_messages' => 10000,
    'consumers' => [], // empty = run every declared consumer; or list specific consumer names
    'multiple_processes' => [], // consumer name => number of parallel processes
],
```

`multiple_processes` spawns several concurrent OS processes against the same consumer/subscription. This is safe: Azure's own peek-lock semantics guarantee a message is only ever handed to one receiver at a time, and Magento's own DB-level `queue_lock` table (keyed by `message_id`) adds a second, transport-independent safety net.

If you'd rather not have cron spawn short-lived processes, run consumers as long-lived processes under `supervisord` instead (`bin/magento queue:consumers:start `) and set `cron_run` to `false` — again, identical to how this is done for RabbitMQ.

Configuration reference
-----------------------

[](#configuration-reference)

All settings live under **Stores &gt; Configuration &gt; MageTips &gt; Azure Service Bus**.

### Service Bus Configurations

[](#service-bus-configurations)

A repeatable grid, one row per topic:

ColumnDescriptionTopicMust exactly match a `communication.xml`/`queue_topology.xml` topic name.HostNamespace endpoint, e.g. `https://your-namespace.servicebus.windows.net/`.Access KeySAS policy name, e.g. `RootManageSharedAccessKey`.Access SecretThe SAS key itself — **encrypted at rest** (`EncryptedArraySerialized` backend model).SubscriptionDefault subscription name for this topic's primary binding (see fan-out for how additional bindings resolve their own).There's no fallback between rows for most call sites (`AsbTopicConfigMapper`) — every topic your topology declares needs its own row, including reply topics for [RPC](#synchronous--rpc-topics).

Each row is keyed by **topic name**, and a consumer process runs from the CLI with no storefront/website context, so it can't resolve a per-website scope at runtime. If you need separate configuration per business line (e.g. a B2C and a B2B website on the same Magento instance, each with its own Azure namespace or credentials), give each one its **own topic name** (e.g. `b2c_sales_order_export` / `b2b_sales_order_export`), each with its own `queue_consumer.xml` entry and its own row in this grid — rather than relying on store-scoped config against a shared topic name.

### Topology

[](#topology)

FieldDefaultDescriptionAutomatically Create Topics on setup:upgradeDisabledSee [Topology installation](#topology-installation-setupupgrade).Max Delivery Count10 (Azure's own default)Delivery attempts before Azure auto-dead-letters a message. Applied when a subscription is created; existing subscriptions aren't retroactively updated.### Message Log Cleanup

[](#message-log-cleanup)

FieldDefaultDescriptionEnable Message Log CleanupDisabledTurns the cleanup cron on/off.Archive Before DeleteEnabled (once cleanup is on)Copy expired rows to the archive table before deleting, vs. deleting outright.Retention (Days)30How old a message must be (by `created_at`) before cleanup.Cleanup Frequency—Nightly or Weekly, always runs at 02:00. Controls *when*, not *how far back* — that's Retention (Days).See [Message log, archiving, and cleanup](#message-log-archiving-and-cleanup) for the full picture.

Dead-lettering
--------------

[](#dead-lettering)

There are two distinct dead-letter mechanisms, covering two different kinds of failure:

- **Local/application-level** — `Queue::reject($envelope, false, $reason)` is used for permanent failures (e.g. a message that fails to decode). The message is completed off the live queue immediately and recorded via `MageTips\Azure\Api\DeadLetterQueueInterface`, so it shows up right away in the **Message Log** grid (dead-letter flag, reason, delivery count) with no round-trip to Azure needed to see it.
- **Azure-native** — `Queue::reject($envelope, true)` is used for transient failures: the peek-lock is released and Azure's own server-side delivery-count tracking takes over, automatically moving the message to that subscription's native `$DeadLetterQueue` sub-queue once **Max Delivery Count** is exceeded. This lives entirely in Azure and is invisible to the Message Log grid.

For the Azure-native case, this module provides both a CLI and an admin page to see and act on what's sitting in a topic's dead-letter sub-queue(s) — if a topic has more than one subscription (fan-out), every subscription's dead-letter sub-queue is reported/acted on, labeled by subscription:

- `bin/magento magetips:azure:deadletter:list  [--limit=50]` — read-only listing, per subscription.
- `bin/magento magetips:azure:deadletter:requeue  [--count=1]` — re-publishes the oldest N dead-lettered messages back onto the live topic, per subscription.
- `bin/magento magetips:azure:deadletter:purge  [--count=1]` — permanently removes the oldest N, per subscription.
- **Azure Service Bus &gt; Dead Letters** (admin) — a live snapshot across every configured topic and subscription (up to 20 messages per subscription), refreshed on every page load. All messages are shown in a single unified table with Topic/Subscription columns, so the page stays usable as the number of topics/subscriptions/messages grows — client-side sorting, a search box, and pagination are handled by [DataTables](https://datatables.net) (MIT licensed, vendored locally under `view/adminhtml/web` rather than loaded from a CDN). This is deliberately client-side only: the server-side fetch stays capped per subscription regardless of what's shown/sorted/filtered in the browser, since Azure's classic REST API has no server-side offset-based pagination to page through in the first place — a "Requeue Oldest" / "Purge" action pair per subscription sits above the table for the actual per-subscription actions.

Both the CLI and the admin page act on the **oldest N** messages, not "the specific row you're looking at" — the classic Service Bus REST API has no addressable per-message access (only sequential receive from the front of the sub-queue), and peek-locks expire in 30-60 seconds, so there's no reliable way to act on a specific message referenced from an earlier list/page-load. Each requeue/purge receives-with-lock and acts immediately in the same call, with no gap a lock could expire across.

Message log, archiving, and cleanup
-----------------------------------

[](#message-log-archiving-and-cleanup)

Every message `MessageQueueConsumer` processes is logged to the `magetips_azure_consumer` table, visible in the admin under the **Azure Service Bus** menu:

- **Azure Service Bus &gt; Message Log** — every consumed message: topic, consumer, event ID, delivery count, dead-letter status, and processing status (Success/Pending). Click a row for full detail, including the message body (pretty-printed if it's JSON) and, for dead letters, the exception/reason. Delete individual rows or select several and use the "Delete" mass action — there's no export button on this grid, since these rows are meant to get cleaned up, not archived via download.
- **Azure Service Bus &gt; Archived Messages** — same columns as the live log plus "Original ID" and "Archived At". Delete individual or bulk rows; no requeue/restore action, since archived messages are kept for reference (and CSV/XML export) rather than re-processing — re-publish via the topic's publisher if you need something back in the live queue.

Both grids support standard Magento UI-component filtering and sorting.

The `magetips_azure_consumer` table grows with every processed message, so any long-running installation needs a retention policy — see the **Message Log Cleanup** fields in [Configuration reference](#configuration-reference). When enabled, a nightly/weekly cron (`magetips_azure_message_log_cleanup`) batches through rows older than the retention window (200 at a time, so a large backlog doesn't attempt one huge delete), archiving each one first if configured to. A failure on one row is logged and skipped rather than aborting the rest of the batch — failures go to `var/log/azure_service_bus.log`.

Admin UI reference
------------------

[](#admin-ui-reference)

All under a top-level **Azure Service Bus** menu (`MageTips_Azure::azure_top`, sort order 65):

Menu itemController routeACL resourceMessage Log`magetips_azure/messagelog/index``MageTips_Azure::message_log`Archived Messages`magetips_azure/messagelogarchive/index``MageTips_Azure::message_log_archive`Dead Letters`magetips_azure/deadletter/index``MageTips_Azure::dead_letter`Config section itself lives under **Stores &gt; Configuration &gt; MageTips &gt; Azure Service Bus**, gated by `MageTips_Azure::system_config`.

CLI command reference
---------------------

[](#cli-command-reference)

CommandPurpose`magetips:azure:deadletter:list  [--limit=50]`List dead-lettered messages, every subscription on the topic.`magetips:azure:deadletter:requeue  [--count=1]`Re-publish the oldest N dead-lettered messages per subscription.`magetips:azure:deadletter:purge  [--count=1]`Permanently remove the oldest N dead-lettered messages per subscription.`bin/magento queue:consumers:start ` and `bin/magento queue:consumers:list` are plain Magento core commands, not Azure-specific — every consumer declared in your `queue_consumer.xml` shows up there automatically.

Logging
-------

[](#logging)

Everything this module logs goes to its own dedicated channel/file, **not** Magento's general `system.log`/`exception.log`:

- File: `var/log/azure_service_bus.log`
- Monolog channel name: `magetips_azure`
- Wired via `di.xml` virtual types (`MageTips\Azure\Logger\Handler` / `MageTips\Azure\Logger\AzureLogger`), the documented Magento pattern for a module-specific log file — not custom PHP classes.

Covers: topology installation results (including harmless "already exists" 409s), setup:upgrade failures, message log cleanup runs, dead-letter subscription read errors, and anything else logged by classes that inject a generic `Psr\Log\LoggerInterface` (they get this channel via DI preference, not Magento's default).

Cron jobs
---------

[](#cron-jobs)

JobGroupScheduleClassPurpose`magetips_azure_message_log_cleanup``default``0 2 * * *` by default, overridden by the **Cleanup Frequency** admin field (writes to `crontab/default/jobs/magetips_azure_message_log_cleanup/schedule/cron_expr`, same mechanism `Magento_Cron`'s `Config\Backend\Product\Alert`/`Sitemap` use)`MageTips\Azure\Cron\PurgeConsumerLog`Archives/deletes expired message log rows. No-op unless **Enable Message Log Cleanup** is on.Consumer scheduling is **not** a cron this module owns — see [Running consumers](#running-consumers) for why that's deliberately left to Magento's own `Magento_MessageQueue::consumers_runner` job.

Key classes
-----------

[](#key-classes)

ClassRole`MessageQueue\Queue`One consumer's binding: resolves its Azure topic + subscription via `QueueTopicResolver`, implements dequeue/ack/reject/renewLock/push.`MessageQueue\Exchange`Publish side: sends to a topic, and for synchronous topics, waits for and returns the reply.`System\QueueTopicResolver`Resolves a Magento queue name (binding destination) to its Azure topic and subscription — the piece that makes fan-out and RPC reply queues work.`System\Config` / `System\AzureTopicsConfig`Read the per-topic admin config grid (host/credentials/subscription).`Service\TopologyInstaller`Creates topics/subscriptions/rules on Azure from `queue_topology.xml`, one subscription per binding.`Service\ServiceBusClientProxy`Caches one Azure REST client connection per topic for 120 seconds, to avoid reconnecting on every call.`Service\DeadLetterReader`Reads/requeues/purges Azure's native per-subscription dead-letter sub-queue.`Queue\MessageQueueConsumer`The `consumerInstance` every `queue_consumer.xml` entry uses — adapted from `Magento\Framework\MessageQueue\Consumer` with plain constructor DI, Azure-specific audit logging, and dead-letter recording.`Model\DeadLetterQueue`Local/application-level dead-letter recording (see [Dead-lettering](#dead-lettering)).Known limitations
-----------------

[](#known-limitations)

- **No offline provisioning by default.** With **Automatically Create Topics** left at its default (disabled), a fresh deployment against a brand-new Azure namespace needs either that setting enabled with sufficiently-privileged credentials, or topics provisioned out-of-band.
- **No addressable per-message actions.** Dead-letter requeue/purge and admin actions always target the *oldest N* messages — the classic Service Bus REST API has no "act on this specific message I saw earlier" capability, and peek-locks expire in 30-60 seconds.
- **Reply topics for RPC must be declared and configured manually** — Azure has no concept of an ad-hoc reply queue the way AMQP does.
- **`AsbTopicConfigMapper` has no cross-topic credential fallback** — every topic (including RPC reply topics) needs its own admin config row.

License
-------

[](#license)

GNU General Public License v3.0 or later. See [`LICENSE`](LICENSE).

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance90

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

49d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/3b99b5b25fe6f575d36de15b97d69fc4f7542a509b0cf27f7e2fe89370a726f2?d=identicon)[UmarShaikh79](/maintainers/UmarShaikh79)

---

Top Contributors

[![UmarShaikh79](https://avatars.githubusercontent.com/u/11783749?v=4)](https://github.com/UmarShaikh79 "UmarShaikh79 (3 commits)")

---

Tags

adobe-commerceazureazure-service-buscomposer-packagedynamics-365erp-integrationmagentomagento2magento2-extensionmessage-queueopen-sourcephprabbitmq-alternativeservice-bussystem-integration

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/magetips-module-azure/health.svg)

```
[![Health](https://phpackages.com/badges/magetips-module-azure/health.svg)](https://phpackages.com/packages/magetips-module-azure)
```

###  Alternatives

[mollie/magento2

Mollie Payment Module for Magento 2

1142.0M17](/packages/mollie-magento2)[loki/magento2-components

Core module for defining Alpine.js components with advanced AJAX features

1015.1k29](/packages/loki-magento2-components)[run-as-root/magento2-prometheus-exporter

Magento2 Prometheus Exporter

69362.0k](/packages/run-as-root-magento2-prometheus-exporter)[dotdigital/dotdigital-magento2-extension

Dotdigital for Magento 2

50406.2k23](/packages/dotdigital-dotdigital-magento2-extension)[fastly/magento2

Fastly CDN Module for Magento 2.4.x

1564.5M1](/packages/fastly-magento2)[buckaroo/magento2

Buckaroo Magento 2 extension

32426.0k8](/packages/buckaroo-magento2)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
