Como criar filas (queue) personalizadas no Magento 2

Lucas Teixeira dos Santos Santana - Jun 3 '22 - - Dev Community

Contextualizando

Como funciona a Fila?

As filas de mensagens fornecem um mecanismo de comunicação assíncrona no qual o publicador e os inscritos de uma mensagem não se comunicam, nem precisam se comunicar com a fila de mensagens ao mesmo tempo. Quando um remetente coloca uma mensagem em uma fila, ela é armazenada até que o destinatário a receba.

No Magento 2 (Adobe Commerce), o MQF (Message Queue Framework) é um sistema totalmente funcional que permite que um módulo publique mensagens em filas. Também cria consumidores para recebê-los de forma assíncrona.O MQF usa principalmente o RabbitMQ como agente de mensagens, que fornece uma plataforma escalável para enviar e receber mensagens. Também inclui um mecanismo para armazenar mensagens não entregues.

Um sistema básico de fila de mensagens também pode ser configurado sem usar o RabbitMQ. Neste sistema, um adaptador MySQL armazena mensagens no banco de dados. Existem três tabelas no banco de dados (queue, queue_message e queue_message_status) que gerenciam a cron jobs para as filas de mensagens.

RabbitMQ

O RabbitMQ é um serviço de mensageria de código aberto que oferece um sistema de mensagens confiável, altamente disponível, escalável e portátil. O sistema de fila de mensagens deve ser estabelecido antes de instalar o Magento.

As filas de mensagens fornecem um mecanismo de comunicação assíncrona no qual o remetente e o destinatário de uma mensagem não se comunicam. Eles também não precisam se comunicar com a fila de mensagens ao mesmo tempo. Quando um remetente coloca uma mensagem em uma fila, ela é armazenada até que o destinatário as receba. Embora as mensagens fluam pelo RabbitMQ e seus aplicativos, elas só podem ser armazenadas dentro de uma fila. Uma fila é limitada apenas pelos limites de memória e disco do host (seria um grande buffer de mensagem). Muitos produtores podem enviar mensagens que vão para uma fila e muitos consumidores podem tentar receber dados de uma fila.


Código para criar uma fila

communication.xml

O arquivo communication.xml define aspectos do sistema da fila de mensagens que todos os tipos de comunicação possuem em comum, seguindo a estruturas de pastas \{Vendor}\{Module}\etc\communication.xml. Por hora, oferece suporte a conexões AMQP e de banco de dados.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Communication/etc/communication.xsd">
    <topic name="{topic.name}" request="{Vendor}\{Module}\Api\Data\{ServiceName}"/>
    <topic name="{topic.name}" request="{request_type}" response="{response_type}">
        <handler name="{handlerName}" type="{Vendor}\{Module}\Model\{ServiceName}" method="{methodName}"/>
    </topic>
    <topic name="{topic.name}" schema="{Vendor}\{Module}\Api\{ServiceName}::{methodName}">
        <handler name="{handlerName}" type="{Vendor}\{Module}\Model\{ServiceName}" method="{methodName}"/>
    </topic>
</config>
Enter fullscreen mode Exit fullscreen mode

Atributos do nó ‘topic’

A configuração de tópicos é flexível, pois é possível alternar a camada de transporte para tópicos no momento da implantação. Esses valores podem ser sobrescritos no arquivo env.php.

O atributo name é obrigatório. A definição do tópico deve incluir uma request ou um schema. É possível utilizar schema se desejar implementar uma interface de serviço personalizada. Caso contrário, especifique a request. Ao especificar o request, o response deve ser especificado, se o tópico for síncrono.

Atributos Descrição
name Uma string que identifica exclusivamente o tópico. Um nome de tópico deve ser uma série de strings separadas por pontos. A string mais à esquerda deve ser a mais geral, e cada string posterior deve restringir o escopo.
request Especifica o tipo de dados do tópico.
response Especifica o formato da resposta. Esse parâmetro é necessário se estiver definindo um tópico síncrono, caso o tópico seja assíncrono basta omita este parâmetro.
schema A interface que descreve a estrutura da mensagem (o formato deve ser: \{Vendor}\{Module}\Api\{ServiceName}::{methodName}).

Atributos do nó ‘handler’

O nó <handler> especifica a classe onde existe a lógica para manipulação de mensagens e o método que a executa.

Atributos Descrição
name String que define o nome do nó <handler>.
type A classe ou interface que define o <handler>.
method O nome do método que será executado.
disabled Determina se o <handler> está desabilitado. O valor padrão é false.

queue_consumer.xml

Este arquivo define aspectos do sistema de fila de mensagens que todos os tipos de comunicação têm em comum e deve estar localizado na pasta \{Vendor}\{Module}\etc\queue_consumer.xml, e pode possuir mais de um consumidor.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework-message-queue:etc/consumer.xsd">
    <consumer name="{ConsumerName}" queue="{queue_name}" handler="{Vendor}\{Module}\Model\{HandlerName}::{methodName}" connection="{amqp/db}" maxMessages="{integer}" maxIdleTime="{integer}" sleep="{integer}" onlySpawnWhenMessageAvailable="{0/1}"/>
    <consumer name="{ConsumerName}" queue="{queue_name}" consumerInstance="{Vendor}\{Module}\Model\{ConsumerName}" connection="{amqp/db}" maxMessages="{integer}" maxIdleTime="{integer}" sleep="{integer}" onlySpawnWhenMessageAvailable="{0/1}"/>
</config>
Enter fullscreen mode Exit fullscreen mode

Atributos do nó ‘consumer’

Os atributos maxIdleTime e sleep serão tratados apenas por consumidores que foram enviados com o parâmetro maxMessages definido. O atributo onlySpawnWhenMessageAvailable é verificado e validado apenas pela classe \Magento\MessageQueue\Model\Cron\ConsumersRunner que executa processos de consumidor com cron.

Atributos Descrição
name Nome do nó <consumer>.
queue Define o nome da fila para a qual será enviada a mensagem.
handler Especifica a classe ou interface e o método que processa a mensagem. O valor deve ser especificado no formato \{Vendor}\{Module}\{Directory}\{HandlerName}:{methodName}.
consumerInstance O nome da classe que consumirá a mensagem
connection amqp: o nome da conexão deve corresponder ao atributo de conexão no arquivo queue_topology.xml. db: qualquer outro cenário.
maxMessages Especifica o número máximo de mensagens a serem consumidas.
maxIdleTime Define o tempo máximo de espera em segundos para uma nova mensagem da fila. Se nenhuma mensagem for tratada nesse período de tempo, o consumidor enviará. O valor padrão é null.
sleep Especifica o tempo em segundos antes de verificar se uma nova mensagem está disponível na fila. O valor padrão é null, o que equivale a 1 segundo.
onlySpawnWhenMessageAvailable Identifica se um consumidor deve ser gerado somente se houver mensagem disponível na fila relacionada. O valor padrão é null.

Consumidor Handler

Um handler é uma classe com um método que consome uma mensagem. E pode ser definido no nó <topic>, como um nó filho <handler> no arquivo communication.xml, ou como atributo handler no nó <consumer> no arquivo queue_consumer.xml.

Se o consumidor em queue_consumer.xml não tiver um consumerInstance definido, o sistema usará o consumidor padrão \Magento\Framework\MessageQueue\Consumer. Neste caso, caso o nó <consumer> conter o atributo handler, ele será usado, e o nó <handler> no arquivo communication.xml será ignorado.

Se o consumidor no arquivo queue_consumer.xml tiver um consumerInstance definido, então a implementação do consumidor será definido como o atributo handler será utilizado.

queue_topology.xml

O arquivo queue_topology.xml define as regras de roteamento de mensagens e declara filas e trocas, seguindo a estruturas de pastas \{Vendor}\{Module}\etc\queue_topology.xml.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework-message-queue:etc/topology.xsd">
    <exchange name="{exchange.name}" type="topic" connection="{amqp/db}" durable="{true/false}" autoDelete="{true/false}">
        <binding id="{queue_consumer_name}" topic="{communication.topic.name}" destinationType="queue" destination="{queue_consumer_queue}">
            <arguments>
                <argument name="{argument_name}" xsi:type="string">{value}</argument>
            </arguments>
        </binding>
    </exchange>
</config>
Enter fullscreen mode Exit fullscreen mode

Atributos do nó ‘exchange’

Atributos Descrição
name Define o identificador único.
type Especifica o tipo de troca. Deve ser topic.
connection Para conexões AMQP, o nome da conexão é recomendável que se utilize amqp. Para conexões MySQL, o nome da conexão deve ser db.
durable Indica se a exchange é persistente. As exchanges não duráveis são eliminadas quando o servidor é reiniciado. O padrão é true.
autoDelete Indica se a exchange é excluída quando todas as filas terminarem de usá-la. O padrão é false.
internal Se definido como verdadeiro, a exchange não pode ser usada diretamente pelos publishers, mas somente quando vinculada a outras exchanges. O padrão é false.

Atributos do nó ‘binding’

O nó <binding> é um nó filho do nó <exchange>.

Atributos Descrição
id Define o identificador único (recomendável colocar o mesmo valor que está atribuído ao atributo name do arquivo queue_consumer.xml) .
topic O nome de um tópico (colocar o mesmo valor que está atribuído ao atributo name do arquivo communication.xml).
destinationType Deve ser queue.
destination Identifica o nome de uma fila (recomendável colocar o mesmo valor que está atribuído ao atributo queue do arquivo queue_consumer.xml).
autoDeletedisabled Determina se o <binding> está desabilitado. O valor padrão é false.

queue_publisher.xml

O arquivo queue_publisher.xml define qual conexão e troca usar para publicar mensagens para um tópico específico, seguindo a estruturas de pastas \{Vendor}\{Module}\etc\queue_publisher.xml.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework-message-queue:etc/publisher.xsd">
    <publisher topic="{communication.topic.name}">
        <connection name="{amqp/db}" exchange="{exchange.name}" disabled="{true/false}"/>
    </publisher>
</config>
Enter fullscreen mode Exit fullscreen mode

Atributos do nó ‘publisher’

Atributos Descrição
topic (obrigatório) O nome de um tópico (colocar o mesmo valor que está atribuído ao atributo name do arquivo communication.xml).
disabled Determina se esta fila está desabilitada. O valor padrão é false.

Atributos do nó ‘connection’

O nó <connection> é um nó filho do elemento <publisher>. Não deve haver mais de uma <connection> habilitada para um <publisher>. Caso o nó <connection> esteja omitido o elemento de conexão, a conexão padrão amqp do magento será usada no atributo exchange.

Atributos Descrição
name (obrigatório) amqp: o nome da conexão deve corresponder ao atributo de conexão no arquivo queue_topology.xml. db: qualquer outro cenário.
exchange O nome da exchange na qual vai publicar a mensagem (colocar o mesmo valor que está atribuído ao atributo name do nó <exchange> do arquivo queue_topology.xml). O nome da exchange do sistema padrão é magento.
disabled Determina se esta fila está desabilitada. O valor padrão é false.

Finalizando

Valores entre chaves ({test}) devem ser alterados na implementação do código.

Habilitando as alterações

Apague os arquivos que são gerados na compilação do Magento e execute o comando PHP para gerar a configuração das injeções de dependência e todas as classes ausentes que precisam ser geradas (proxys, interceptors, etc) e para limpar todos os caches de armazenamento em cache do processos.

rm -rf var/generation/
rm -rf generated/
php bin/magento setup:di:compile
php bin/magento cache:clean
php bin/magento flush
Enter fullscreen mode Exit fullscreen mode

Diretórios e Arquivos

Segue a a lista de diretórios e arquivos que devem ser criados.

- app/
  - code/
    - {Vendor}/
        - {Module}/
          - etc/
            - communication.xml
            - queue_consumer.xml
            - queue_topology.xml
            - queue_publisher.xml
            - module.xml
          - registration.php
          - composer.json
Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .