Fluxo order.created

Order publica, Payment consome

Você conecta order-service e payment-service via Kafka, sem dependência síncrona.

Avançado 55 min 35 pontos Leitura 0%

Nesta aula você vai

  • Publicar `order.created.v1` após criação de pedido
  • Consumir evento no serviço de pagamento em Go
  • Implementar tratamento básico de erro e logs de rastreio

Order publica, Payment consome

Objetivos

  • Publicar order.created.v1 após criação de pedido
  • Consumir evento no serviço de pagamento em Go
  • Implementar tratamento básico de erro e logs de rastreio

Pré-requisitos

  • Contrato order.created.v1 modelado
  • order-service e payment-service ativos
  • Kafka configurado no Compose

Conceito

O fluxo de pedido para pagamento é crítico e não pode depender de chamada HTTP em cadeia. Se o payment-service estiver indisponível por alguns segundos, o pedido ainda deve ser criado com sucesso, e o processamento deve ocorrer depois.

Kafka permite exatamente esse desacoplamento temporal: o order-service publica o evento e segue. O consumidor no payment-service processa quando estiver pronto, mantendo confiabilidade e capacidade de reprocessamento.

Nesta aula você implementa producer em Python e consumer em Go, incluindo parsing de payload, logs de offset e criação inicial de status de pagamento.

Estrutura de arquivos

services/order-service/app/events/order_publisher.py
services/order-service/app/service/order_service.py
services/payment-service/internal/consumers/order_created_consumer.go
services/payment-service/internal/service/payment_service.go
contracts/events/order-created.v1.json

Passo a passo

  1. Implementar publisher no order-service (Python)
# app/events/order_publisher.py
import json
from kafka import KafkaProducer

class OrderPublisher:
    def __init__(self):
        self.producer = KafkaProducer(
            bootstrap_servers="kafka:9092",
            value_serializer=lambda v: json.dumps(v).encode("utf-8"),
        )

    def publish_order_created(self, event: dict):
        self.producer.send("order.created.v1", key=event["orderId"].encode("utf-8"), value=event)
        self.producer.flush()
  1. Publicar evento no fluxo de criação de pedido
# app/service/order_service.py
event = build_order_created_event(order, correlation_id)
self.publisher.publish_order_created(event)
  1. Implementar consumidor em Go
// internal/consumers/order_created_consumer.go
package consumers

import (
  "context"
  "encoding/json"
  "log"

  "github.com/segmentio/kafka-go"
)

type OrderCreatedEvent struct {
  EventID   string  `json:"eventId"`
  OrderID   string  `json:"orderId"`
  CustomerID string `json:"customerId"`
  Amount    float64 `json:"amount"`
  Currency  string  `json:"currency"`
}

func StartOrderCreatedConsumer() {
  reader := kafka.NewReader(kafka.ReaderConfig{
    Brokers: []string{"kafka:9092"},
    Topic:   "order.created.v1",
    GroupID: "payment-service-order-group",
  })

  for {
    msg, err := reader.ReadMessage(context.Background())
    if err != nil {
      log.Printf("erro no consumo: %v", err)
      continue
    }

    var event OrderCreatedEvent
    if err := json.Unmarshal(msg.Value, &event); err != nil {
      log.Printf("payload inválido offset=%d", msg.Offset)
      continue
    }

    log.Printf("order.created recebido orderId=%s partition=%d offset=%d", event.OrderID, msg.Partition, msg.Offset)
  }
}
  1. Iniciar consumer no main.go do payment-service
go consumers.StartOrderCreatedConsumer()
router.Run(":8080")

Como testar

  1. Subir serviços:
docker compose -f infra/docker-compose.yml up --build -d kafka order-service payment-service
  1. Criar pedido:
curl -s -X POST http://localhost:8000/orders \
  -H "Content-Type: application/json" \
  -H "X-Correlation-Id: corr-pay-100" \
  -d '{"customer_id":"cli-100","total_amount":349.90,"currency":"BRL"}'
  1. Verificar consumo:
docker compose -f infra/docker-compose.yml logs -f payment-service

Saída esperada:

order.created recebido orderId=<id> partition=<n> offset=<n>
  1. Testar múltiplos pedidos:
for i in 1 2 3; do
  curl -s -X POST http://localhost:8000/orders \
    -H "Content-Type: application/json" \
    -d "{\"customer_id\":\"cli-$i\",\"total_amount\":99.$i,\"currency\":\"BRL\"}" >/dev/null
done

Dicas de projeto

  • Producer deve publicar só depois de persistir pedido.
  • Consumer deve separar parsing e regra de negócio.
  • Logue partition, offset e orderId.
  • Prepare idempotência para lidar com reentrega.

Erros comuns

  • Fazer chamada REST de volta para confirmar recebimento.
  • Consumir sem validar payload obrigatório.
  • Esquecer de tratar erro de deserialização.
  • Assumir ordem global em múltiplas partições.

Resumo

Order e Payment agora estão integrados por eventos, com publicação e consumo reais no Kafka. O fluxo ficou desacoplado temporalmente e pronto para tratar consistência eventual de forma explícita.