Fluxo order.created

Modelando order.created

Você modela o contrato `order.created.v1` com foco em semântica de domínio e evolução segura.

Avançado 40 min 25 pontos Leitura 0%

Nesta aula você vai

  • Definir payload enxuto para acionar o pagamento
  • Adicionar metadados de rastreio e versionamento
  • Evitar acoplamento do contrato ao banco do order-service

Modelando order.created

Objetivos

  • Definir payload enxuto para acionar o pagamento
  • Adicionar metadados de rastreio e versionamento
  • Evitar acoplamento do contrato ao banco do order-service

Pré-requisitos

  • Módulo Kafka concluído
  • order-service e payment-service ativos
  • Conhecimento de JSON Schema

Conceito

Evento de domínio é um contrato público. Quando o order-service publica order.created, ele está prometendo para todo o ecossistema que aquele payload terá significado estável. Se o contrato vaza detalhe interno (ex.: estrutura da tabela), a evolução do serviço fica travada.

Um bom evento contém o necessário para reação do consumidor, sem excesso. Para payment-service, interessam orderId, customerId, amount, currency e metadados de correlação. Campos não usados por ninguém só aumentam acoplamento.

Nesta aula, você cria order.created.v1 com JSON Schema, inclui validação no producer e prepara o contrato para crescer sem quebrar consumidores existentes.

Estrutura de arquivos

contracts/events/order-created.v1.json
services/order-service/app/events/order_created_event.py
services/order-service/app/service/order_service.py
docs/architecture/events.md

Passo a passo

  1. Criar contrato JSON Schema (contracts/events/order-created.v1.json)
{
  "title": "order.created.v1",
  "type": "object",
  "required": [
    "eventId",
    "occurredAt",
    "orderId",
    "customerId",
    "amount",
    "currency",
    "status"
  ],
  "properties": {
    "eventId": { "type": "string" },
    "occurredAt": { "type": "string", "format": "date-time" },
    "orderId": { "type": "string" },
    "customerId": { "type": "string" },
    "amount": { "type": "number", "minimum": 0.01 },
    "currency": { "type": "string", "minLength": 3, "maxLength": 3 },
    "status": { "type": "string", "enum": ["PENDING_PAYMENT"] },
    "correlationId": { "type": "string" }
  }
}
  1. Criar construtor do evento no order-service
# app/events/order_created_event.py
from datetime import datetime, timezone
import uuid

def build_order_created_event(order: dict, correlation_id: str) -> dict:
    return {
        "eventId": str(uuid.uuid4()),
        "occurredAt": datetime.now(timezone.utc).isoformat(),
        "orderId": order["id"],
        "customerId": order["customer_id"],
        "amount": order["total_amount"],
        "currency": order["currency"],
        "status": "PENDING_PAYMENT",
        "correlationId": correlation_id,
    }
  1. Integrar builder ao fluxo do serviço
# app/service/order_service.py
from app.events.order_created_event import build_order_created_event

def create(self, customer_id: str, total_amount: float, currency: str, correlation_id: str):
    order = self.repo.save(customer_id, total_amount, currency)
    event = build_order_created_event(order, correlation_id)
    self.publisher.publish("order.created.v1", key=order["id"], value=event)
    return order
  1. Documentar semântica do evento
<!-- docs/architecture/events.md -->
## order.created.v1
- Publicado após persistência do pedido
- Status inicial fixo: PENDING_PAYMENT
- Consumidor principal: payment-service

Como testar

  1. Subir order-service e Kafka:
docker compose -f infra/docker-compose.yml up --build -d kafka order-service
  1. Criar pedido:
curl -s -X POST http://localhost:8000/orders \
  -H "Content-Type: application/json" \
  -H "X-Correlation-Id: corr-ord-001" \
  -d '{"customer_id":"cli-77","total_amount":249.9,"currency":"BRL"}'
  1. Consumir evento de teste no tópico:
docker compose -f infra/docker-compose.yml exec kafka \
  kafka-console-consumer.sh --bootstrap-server kafka:9092 --topic order.created.v1 --from-beginning --max-messages 1

Saída esperada: JSON contendo orderId, amount, currency, status.

Dicas de projeto

  • Inclua apenas campos necessários para ação do consumidor.
  • Use currency explícita; nunca assuma moeda padrão.
  • Nomeie tópico com versão (order.created.v1).
  • Registre owner e regra de publicação do evento.

Erros comuns

  • Publicar evento antes de persistir pedido.
  • Enviar estrutura de banco em vez de contrato de integração.
  • Não incluir eventId/occurredAt.
  • Misturar campos de UI no evento de domínio.

Resumo

Você modelou order.created.v1 com semântica clara, versionamento e campos essenciais para pagamento. Esse contrato reduz acoplamento e viabiliza integração segura entre serviços.