Simulador de Eventos

Projete e trace fluxos de eventos entre microsserviços — desde a publicação até o consumo e as reações em cadeia.

Objetivo

Neste laboratório você vai projetar fluxos de eventos entre microsserviços, traçar seu percurso completo e antecipar os problemas que podem surgir em uma arquitetura event-driven.

Os eventos são o sistema nervoso de uma arquitetura distribuída. Entender como eles fluem é fundamental para projetar sistemas desacoplados e resilientes.

Conceitos prévios

Antes de começar, certifique-se de entender a diferença entre:

ConceitoDescriçãoExemplo
ComandoSolicitação para fazer algoCreateOrder
EventoNotificação de algo que já aconteceuOrderCreated
QuerySolicitação de informaçãoGetOrderStatus

Os eventos são fatos imutáveis — algo que já ocorreu e não pode ser desfeito. Os comandos são intenções — podem ser rejeitados.


Exercício 1: Projetar um fluxo de eventos

Cenário

Um usuário compra um produto no seu e-commerce. Projete o fluxo completo de eventos desde o momento em que ele clica em “Comprar” até receber a confirmação.

Serviços envolvidos

  • Serviço de Pedidos: cria e gerencia pedidos
  • Serviço de Estoque: reserva e dá baixa no estoque
  • Serviço de Pagamentos: processa a cobrança
  • Serviço de Notificações: envia e-mails e push
  • Serviço de Analytics: registra métricas de negócio

Sua tarefa

Complete o diagrama de eventos:

Usuário clica em "Comprar"


[Serviço de Pedidos]
    │ publica: OrderCreated { orderId, userId, items, total }

    ├──► [Serviço de Estoque]
    │       consome: OrderCreated
    │       ação: reservar estoque
    │       publica: _______________

    ├──► [Serviço de Pagamentos]
    │       consome: _______________
    │       ação: processar cobrança
    │       publica: _______________

    ├──► [Serviço de Notificações]
    │       consome: _______________
    │       ação: _______________

    └──► [Serviço de Analytics]
            consome: _______________
            ação: _______________

Solução

Ver fluxo completo
Usuário clica em "Comprar"


[Serviço de Pedidos]
    │ publica: OrderCreated { orderId, userId, items, total }

    ├──► [Serviço de Estoque]
    │       consome: OrderCreated
    │       ação: reservar estoque para os itens
    │       publica: StockReserved { orderId, items }
    │              ou StockInsufficient { orderId, items }

    ├──► [Serviço de Pagamentos]
    │       consome: StockReserved
    │       ação: processar cobrança com o provedor
    │       publica: PaymentCompleted { orderId, transactionId }
    │              ou PaymentFailed { orderId, reason }

    ├──► [Serviço de Notificações]
    │       consome: PaymentCompleted
    │       ação: enviar e-mail de confirmação ao usuário
    │       consome: PaymentFailed
    │       ação: enviar e-mail de falha ao usuário

    └──► [Serviço de Analytics]
            consome: OrderCreated, StockReserved, PaymentCompleted
            ação: registrar métricas de conversão e receita

Exercício 2: Lidar com o caminho infeliz

Cenário

O que acontece quando algo falha no meio do fluxo? Projete as compensações.

Caso 1: O estoque foi reservado, mas o pagamento falhou

OrderCreated → StockReserved → PaymentFailed


                              E agora?

Sua tarefa: Qual evento o serviço de pagamentos deve publicar? Quem o consome? Que ação ele toma?

Ver solução
PaymentFailed { orderId, reason }

    ├──► [Serviço de Estoque]
    │       consome: PaymentFailed
    │       ação: liberar estoque reservado
    │       publica: StockReleased { orderId, items }

    ├──► [Serviço de Pedidos]
    │       consome: PaymentFailed
    │       ação: marcar pedido como falho
    │       publica: OrderCancelled { orderId, reason }

    └──► [Serviço de Notificações]
            consome: OrderCancelled
            ação: notificar o usuário de que o pagamento falhou

Este é o padrão Saga com coreografia: cada serviço reage aos eventos e executa compensações quando algo falha. Não há um orquestrador central.

Caso 2: O serviço de estoque está fora do ar

OrderCreated → [Estoque: FORA DO AR] → ???

Sua tarefa: O que acontece com o evento OrderCreated? Ele se perde? É reprocessado?

Ver solução

Se você usar um message broker com filas duráveis (RabbitMQ, Kafka):

  1. O evento OrderCreated fica na fila aguardando
  2. Quando o serviço de estoque volta, consome os eventos pendentes
  3. O processamento continua normalmente (com atraso)

Chave: A fila atua como buffer temporário. O evento não se perde enquanto a fila for durável e as mensagens forem persistentes.

Consideração: Se o serviço ficar fora do ar por muito tempo, a fila cresce. Você precisa de:

  • Alertas por tamanho de fila
  • TTL nas mensagens para evitar processar eventos muito antigos
  • Lógica de compensação caso o evento já não seja relevante

Exercício 3: Ordenação de eventos

O problema

Dois eventos chegam ao serviço de estoque:

  1. StockUpdated { productId: "ABC", quantity: 100 } (timestamp: 10:00:01)
  2. StockUpdated { productId: "ABC", quantity: 50 } (timestamp: 10:00:00)

O evento 2 foi publicado primeiro, mas chegou depois. Se você processar na ordem de chegada, o estoque fica em 50 (incorreto — deveria ser 100).

Sua tarefa

Como garantir a ordem correta? Avalie estas estratégias:

EstratégiaPrósContras
Ordenar por timestampSimplesRelógios não sincronizados entre serviços
Número de sequênciaOrdem garantidaRequer coordenação entre publishers
Partição por keyOrdem dentro da partiçãoLimita o paralelismo
Versão otimistaNão requer ordem globalRequer lógica de resolução de conflitos
Ver recomendação

A estratégia mais prática para a maioria dos casos é partição por key:

  • No Kafka: usar productId como partition key
  • Todos os eventos do mesmo produto vão para a mesma partição
  • Dentro de uma partição, a ordem está garantida
  • Produtos diferentes são processados em paralelo

Para casos em que você precisa de ordem global, use um número de sequência gerado pelo publisher e rejeite eventos com sequência menor que a última processada.


Exercício 4: Projete seu próprio fluxo

Sua tarefa

Escolha um destes cenários e projete o fluxo completo de eventos:

Opção A: Sistema de reservas de hotel

  • Serviços: Reservas, Quartos, Pagamentos, Notificações
  • Fluxo: usuário reserva → verificar disponibilidade → cobrar → confirmar

Opção B: Plataforma de delivery

  • Serviços: Pedidos, Restaurantes, Entregadores, Tracking, Notificações
  • Fluxo: usuário pede → restaurante aceita → entregador designado → entrega

Opção C: Sistema de assinaturas

  • Serviços: Usuários, Assinaturas, Pagamentos, Acesso, Notificações
  • Fluxo: usuário assina → cobrança recorrente → renovação/cancelamento

Para cada um, defina:

  1. Os eventos principais (caminho feliz)
  2. Os eventos de compensação (caminho infeliz)
  3. Qual serviço publica e quem consome cada evento
  4. Como você lida com as falhas em cada etapa

Reflexão

  1. Quantos eventos você precisou para um fluxo “simples”?
  2. Quão difícil foi projetar as compensações?
  3. Você preferiria um orquestrador central (Saga orquestrada) ou coreografia?
  4. Como você depuraria um problema em um fluxo de 5+ eventos?

Os sistemas event-driven são poderosos, mas complexos. A chave é projetar os fluxos antes de escrever código — e sempre pensar no que acontece quando algo falha.