Este repositório mantém a configuração do RabbitMQ compartilhado por diferentes módulos. O arquivo config/definitions.json provisiona a Dead Letter Queue (DLQ) e as filas de retry com atraso do fluxo de importação de inscrições.
Responsabilidades: o RabbitMQ encaminha e armazena mensagens; o consumidor Laravel decide quando uma falha permite retry, limita as tentativas e controla a idempotência por
(opportunity_id, registration_id). A infraestrutura não deduplica mensagens nem envia e-mails.
Mapas Culturais
|
v
exchange_notification --[module_import_registration_draft]--> queue_import_registration
^ |
| v
| Consumidor Laravel
| |
| +---------------------------------------+-----------------+
| | | |
| Sucesso / Falha segura Falha definitiva
| duplicidade para retry ou mensagem inválida
| | | |
| ACK v v
| exchange_notification_retry NACK (requeue=false)
| | |
| +----------------------------------+ v
| | | | exchange_notification_dlx
| v v v |
| retry_1 (1 min) retry_2 (5 min) retry_3 (15 min) v
| | | | queue_import_registration_dlq
+---------------------+-----------------+----------------+
(dead-letter após TTL)
Nomes completos das filas de espera: queue_import_registration_retry_1, queue_import_registration_retry_2 e queue_import_registration_retry_3.
A fila principal recebe mensagens da exchange exchange_notification, usando a routing key module_import_registration_draft. Essa exchange, a fila queue_import_registration e seu binding já devem existir no broker compartilhado: não são criados pelo definitions.json deste repositório.
| Recurso | Nome | Finalidade |
|---|---|---|
Exchange direct |
exchange_notification_dlx |
Recebe mensagens rejeitadas definitivamente |
| Fila durável | queue_import_registration_dlq |
Guarda mensagens que exigem investigação |
| Binding da DLQ | module_import_registration_draft_dlq |
Encaminha mensagens à DLQ |
| Policy | import-registration-dlx |
Configura a DLX somente na fila principal |
Exchange direct |
exchange_notification_retry |
Recebe publicações de retry feitas pelo Laravel |
| Fila durável | queue_import_registration_retry_1 |
Aguarda 60 segundos |
| Fila durável | queue_import_registration_retry_2 |
Aguarda 300 segundos |
| Fila durável | queue_import_registration_retry_3 |
Aguarda 900 segundos |
Os bindings da exchange exchange_notification_retry usam as routing keys:
module_import_registration_draft_retry_1module_import_registration_draft_retry_2module_import_registration_draft_retry_3
Cada fila de retry possui x-message-ttl e usa dead-lettering para retornar à exchange principal exchange_notification, pela routing key module_import_registration_draft. Não há consumidores nas filas de retry.
A policy import-registration-dlx aplica-se somente à fila queue_import_registration. Mensagens rejeitadas com nack(requeue=false) seguem para exchange_notification_dlx, com routing key module_import_registration_draft_dlq, e daí para a DLQ; a DLQ não devolve mensagens automaticamente à fila principal.
- Docker e Docker Compose disponíveis.
- Rede Docker externa
labexistente, conforme a configuração atual do projeto (docker network inspect lab). - Permissão para executar comandos no contêiner chamado
rabbitmq. - Virtual host
/existente, com usuários e permissões adequadas. - Exchange principal
exchange_notification(do tipo esperado pelas aplicações), fila principalqueue_import_registratione respectivo binding já provisionados. docker-compose.ymlmontandoconfig/definitions.jsoncomo/etc/rabbitmq/definitions.json:ro.- Configuração anterior de
load_definitionsno boot removida. Não é necessário manterconfig/rabbitmq.confvazio se não houver outras referências ao arquivo.
Este repositório não cria usuários, senhas, permissões nem o virtual host por meio das definições. Em uma instância nova, permita que a inicialização normal do RabbitMQ crie os recursos iniciais conforme a configuração da imagem e do ambiente; verifique-os antes da importação.
No diretório que contém docker-compose.yml, inicie o contêiner caso ainda não esteja em execução:
docker compose up -d rabbitmqAguarde o broker ficar operacional:
docker exec rabbitmq rabbitmqctl await_startup --timeout 300Confirme que o virtual host e os usuários esperados existem:
docker exec rabbitmq rabbitmqctl list_vhosts
docker exec rabbitmq rabbitmqctl list_usersConfira também se o arquivo atualizado está disponível no contêiner:
docker exec rabbitmq cat /etc/rabbitmq/definitions.jsonImporte as definições após a inicialização:
docker exec rabbitmq rabbitmqctl import_definitions /etc/rabbitmq/definitions.jsonA importação é uma etapa obrigatória do provisionamento de instalações novas e de deploys que modifiquem as definições. Ela não ocorre automaticamente durante o boot. Não considere o deploy concluído sem validar os recursos criados.
Uma reinicialização com o volume persistido conserva os recursos existentes; não é necessário limpar ou recriar o volume para atualizar as definições.
Execute:
# Recursos e permissões
docker exec rabbitmq rabbitmqctl list_exchanges -p / name type durable
docker exec rabbitmq rabbitmqctl list_queues -p / name durable messages_ready messages_unacknowledged arguments policy
docker exec rabbitmq rabbitmqctl list_bindings -p /
docker exec rabbitmq rabbitmqctl list_policies -p /
docker exec rabbitmq rabbitmqctl list_permissions -p /Confirme:
- A exchange
exchange_notification_dlx, a filaqueue_import_registration_dlqe seu binding existem. - A policy
import-registration-dlxcontinua apontando somente a fila principal para a DLQ. - A exchange
exchange_notification_retrye as três filas de retry existem, com os bindings e TTLs corretos. - Cada fila de retry aponta seu
x-dead-letter-exchangeparaexchange_notificatione seux-dead-letter-routing-keyparamodule_import_registration_draft. - A exchange, a fila e o binding principais continuam disponíveis para os outros módulos.
- O usuário do Laravel possui permissão para publicar na exchange de retry e consumir da fila principal, conforme a política de acesso do ambiente. Verifique também as permissões necessárias para o dead-lettering entre exchanges.
Não exige um RabbitMQ em execução:
python3 -m unittest discover -s tests -vO arquivo tests/test_definitions.py deve ser versionado. Arquivos gerados automaticamente, como tests/__pycache__/test_definitions.cpython-310.pyc, não devem ser versionados. Inclua no .gitignore, se necessário:
__pycache__/
*.py[cod]
.pytest_cache/Executar somente em desenvolvimento ou homologação, com dados controlados e sem possibilidade de disparar e-mails reais:
- Publique uma mensagem deliberadamente inválida na exchange principal, com a routing key
module_import_registration_draft. - Verifique que o consumidor rejeita a mensagem com
nack(requeue=false). - Confira na interface de gerenciamento se ela saiu da fila principal e chegou à
queue_import_registration_dlq. - Inspecione, se necessário, os cabeçalhos de dead-lettering (por exemplo,
x-death).
Executar somente em homologação, sem consumidor capaz de enviar e-mails reais:
- Publique uma mensagem de teste na exchange
exchange_notification_retry, com routing keymodule_import_registration_draft_retry_1. - Confirme que ela entrou em
queue_import_registration_retry_1. - Após aproximadamente 60 segundos, confirme que saiu da fila de retry e foi roteada para
queue_import_registration. - Repita, se necessário, para as rotas
_retry_2e_retry_3, com esperas aproximadas de 5 e 15 minutos. - Com o PR 4B implantado em ambiente controlado, valide a classificação das falhas, os limites de tentativas e os comportamentos de
ack/nack.
O TTL não é um agendador de precisão: o encaminhamento pode acontecer um pouco depois do intervalo configurado. As filas de retry não devem ter consumidores próprios.
Segurança dos testes: não utilize purge, delete_queue, remoção de volumes ou reenvio indiscriminado de mensagens da DLQ em produção.
- Implante o PR 4A (RabbitMQ) e importe
definitions.jsonapós o broker estar operacional. - Confirme filas, TTLs, bindings, DLQ e permissões do usuário do Laravel.
- Implante o PR 4B (Laravel) inicialmente com
RABBITMQ_IMPORT_REGISTRATION_RETRY_ENABLED=false. - Execute os testes do consumidor e um teste de integração em homologação.
- Habilite
RABBITMQ_IMPORT_REGISTRATION_RETRY_ENABLED=true, recarregue a configuração do Laravel e reinicie o consumidor.
Rollback: para interromper a criação de novos retries, desabilite a flag no Laravel e reinicie o worker. Não remova as filas de retry enquanto houver mensagens pendentes: mensagens já publicadas nelas poderão retornar à fila principal após o TTL, mesmo com a flag desabilitada.
- Nova instalação: iniciar normalmente o broker, verificar vhost/usuários, importar as definições e validar os recursos.
- Ambiente compartilhado: não recriar ou apagar recursos de outros módulos; verificar eventuais conflitos de policies.
- Mensagens na DLQ: investigar a causa antes de qualquer reprocessamento; não há retorno automático da DLQ para a fila principal.
- Estados do Laravel: monitorar
failed,sendingeunknown. O retry automático não se aplica a mensagens inválidas nem a resultados SMTP incertos; o consumidor deve preservar a idempotência. - Monitoramento das filas: acompanhar
queue_import_registration,queue_import_registration_dlq, as três filas de retry e a disponibilidade do consumidor. - TTL: os valores
x-message-ttlsão argumentos das filas existentes. Alterá-los diretamente em uma nova declaração pode provocarPRECONDITION_FAILED; planeje previamente a migração ou uma estratégia de configuração por policies. - Persistência e entrega: filas duráveis e mensagens persistentes ajudam na recuperação, mas o dead-lettering tradicional e a publicação seguida de
acknão fornecem transação única nem garantia de entrega exatamente uma vez. - Segurança: não versionar credenciais reais; restringir acesso às portas
5672e15672; utilizar permissões adequadas por ambiente e acesso ao painel somente pela rede autorizada. - Backup: preservar o volume persistente e seguir o procedimento de backup e restauração da infraestrutura. Não apagar os dados do broker para testar o provisionamento.
NOT_FOUND - no exchange ou mensagem de retry não retorna à fila principal: confirme que exchange_notification e o binding module_import_registration_draft já existem e que as permissões são suficientes.
DLQ não recebe mensagens: verifique se a policy está aplicada à fila principal, se a exchange e o binding da DLQ existem e se o consumidor usa nack com requeue=false para a rejeição definitiva.
Fila de retry não recebe mensagens: verifique se exchange_notification_retry, o binding correspondente e as permissões de publicação estão corretos. Confira também se o retry está habilitado no consumidor Laravel.
Mensagem fica na fila de retry por mais tempo que o TTL: verifique se há falha de roteamento no dead-lettering, se a exchange principal existe e se a fila realmente recebeu os argumentos de TTL/DLX esperados. O prazo é aproximado.
Instância nova sem virtual host ou usuário: verifique se a importação automática durante o boot foi removida e se as variáveis de inicialização do contêiner estão corretas.
PRECONDITION_FAILED ao declarar fila ou exchange: confira a compatibilidade do tipo e dos argumentos existentes. Não exclua recursos em uso para resolver esse erro sem análise de impacto.