Temos um serviço de pagamento que consome dados de duas filas:
clients-processor
: fila com dados de clientes para cadastrarpayment-processor
: fila com dados de um pagamento para ser processado
Esse serviço processa os pagamentos, porém ele só processa pagamentos de clientes que estão cadastrados.
Como tratar o problema de race condition quando um evento de pagamento é recebido primeiro que o evento de cadastro de clientes (sem utilizar bancos de dados). Para simplificar mais temos a premissa que o evento de cadastro de cliente sempre será recebido.
- Uma fila para evento de cadastro de clientes:
clients-processor
- Uma fila para evento de pagamentos:
payment-processor
- Uma fila para reprocessar eventos de pagamentos:
payment-reprocessor
utilizando o plugindelayed_message_exchange
do RabbitMQ
Quando um evento de pagamento é recebido e o cliente ainda não está cadastrado, aumentamos o valor do delay
da mensagem em 1 segundo
. A mensagem é então encaminhada para a fila de reprocessamento. Em algum momento, quando um cliente for efetivamente cadastrado, o pagamento correspondente será processado.
Para exemplificar melhor, o fluxo grama abaixo mostra a abordagem utilizada:
O docker-compose é configurado para executar o RabbitMQ, carregando o plugin necessário que está presente na pasta rabbitmq/plugins
na raiz do projeto.
Para rodar o RabbitMQ execute:
$ docker-compose up
Execute o comando abaixo para começar a consumir as mensagens das filas de clients-processor
, payment-processor
e payment-reprocessor
.
$ go run ./cmd/consumer
Agora basta publicar as mensagens:
$ go run ./cmd/producer payment <clientId>
Para publicar uma mensagem de pagamento para o cliente de clientId informado
$ go run ./cmd/producer client <clientId>
Para publicar uma mensagem de cadastro para o cliente com clientId informado
Para o exemplo, vamos enviar duas mensagens, uma com o pagamento e outra com o novo cliente.
Ao receber um pagamento de um cliente com o ID 1, o pagamento não vai ser processado, a mensagem é enviada para uma fila e o delay vai aumentando, até que a mensagem de cadastro do cliente é recebida, no proximo recebimento do pagamento ele será processado e a operação finaliza.