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.
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-serviceepayment-serviceativos- 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
- 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" }
}
}
- 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,
}
- 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
- 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
- Subir
order-servicee Kafka:
docker compose -f infra/docker-compose.yml up --build -d kafka order-service
- 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"}'
- 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
currencyexplí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.