Como projetar sistemas de workflow para processos longos
1. Fundamentos de Workflows para Processos Longos
Processos longos são workflows cuja execução se estende por horas, dias ou até semanas, diferindo fundamentalmente de transações curtas e síncronas. Enquanto um workflow síncrono é concluído em milissegundos dentro de uma única requisição HTTP, processos longos exigem persistência de estado, tolerância a falhas e capacidade de retomada.
Características principais:
- Duração estendida com pausas entre etapas (ex: aguardando aprovação humana)
- Dependência de eventos externos (webhooks, notificações, timeouts)
- Necessidade de compensação para ações parciais (sagas)
- Rastreamento auditável de cada transição de estado
Casos de uso típicos:
- Aprovações de pedidos com múltiplos níveis hierárquicos
- Integrações bancárias com liquidação em D+1
- Pipelines de ETL que processam terabytes de dados
- Provisionamento de infraestrutura em nuvem
2. Arquitetura Baseada em Máquina de Estados (State Machine)
A modelagem de workflows longos como máquinas de estados finitos é o padrão mais robusto. Cada workflow possui um conjunto definido de estados e transições válidas, representados como grafos direcionados.
Exemplo de definição de máquina de estados para aprovação de pedido:
Estados: [PENDENTE, EM_APROVACAO, APROVADO, REJEITADO, CANCELADO, EXPIRADO]
Transições:
PENDENTE -> EM_APROVACAO (submissão)
EM_APROVACAO -> APROVADO (aprovação gerencial)
EM_APROVACAO -> REJEITADO (rejeição)
PENDENTE -> CANCELADO (cancelamento pelo cliente)
EM_APROVACAO -> EXPIRADO (timeout de 48h)
Persistência de estado em banco relacional:
CREATE TABLE workflow_instances (
id UUID PRIMARY KEY,
workflow_type VARCHAR(100),
current_state VARCHAR(50),
payload JSONB,
created_at TIMESTAMP,
updated_at TIMESTAMP,
version INTEGER DEFAULT 1
);
CREATE TABLE workflow_transitions (
id UUID PRIMARY KEY,
instance_id UUID REFERENCES workflow_instances(id),
from_state VARCHAR(50),
to_state VARCHAR(50),
event VARCHAR(100),
triggered_by VARCHAR(200),
timestamp TIMESTAMP
);
Tratamento de transições inválidas: toda tentativa de transição deve ser validada contra a matriz de estados. Transições inválidas geram exceções e são registradas para auditoria.
3. Orquestração vs. Coreografia em Workflows Longos
Orquestração utiliza um coordenador central que gerencia o fluxo completo:
Orquestrador (Camunda/Temporal)
├── Etapa 1: Validar pedido
├── Etapa 2: Aguardar aprovação (async)
├── Etapa 3: Processar pagamento
└── Etapa 4: Notificar cliente
Coreografia baseia-se em eventos assíncronos entre serviços:
Serviço Pedidos -> Evento "pedido.criado"
└── Serviço Aprovação -> Evento "pedido.aprovado"
└── Serviço Pagamento -> Evento "pagamento.processado"
└── Serviço Notificação -> Evento "cliente.notificado"
Trade-offs:
- Orquestração: maior acoplamento, mas visibilidade total e fluxo explícito
- Coreografia: baixo acoplamento, mas difícil rastrear fluxos complexos
- Para processos longos, a orquestração é geralmente preferível por permitir rollback coordenado
4. Mecanismos de Resiliência e Retentativas
Estratégias para falhas temporárias e permanentes em workflows longos:
Backoff exponencial com jitter:
funcao calcular_espera(tentativa):
base = min(2^tentativa * 1000, 30000) // 1s, 2s, 4s... até 30s
jitter = random(0, 0.1 * base)
retorna base + jitter
Dead Letter Queue (DLQ) para falhas não recuperáveis:
Configuração DLQ:
- max_retentativas: 5
- dlq_topic: "workflow_falhas_permanentes"
- acao_compensatoria: "reverter_pagamento"
Compensação via saga:
Transacao 1: Reservar estoque
Sucesso -> Transacao 2: Debitar cartao
Sucesso -> Transacao 3: Enviar email
Falha -> Compensar: Reembolsar cartao + Liberar estoque
5. Persistência e Rastreamento de Estado ao Longo do Tempo
Snapshots de estado permitem recuperação após falhas catastróficas:
Checkpoint a cada 5 etapas:
{
"instance_id": "abc-123",
"current_state": "EM_APROVACAO",
"snapshot_version": 3,
"payload": {"pedido_id": 456, "valor": 1500.00},
"completed_steps": ["validacao", "reserva_estoque"],
"pending_actions": ["aguardar_aprovacao"]
}
Event sourcing para auditoria completa:
Eventos registrados:
1. PedidoCriado { pedido_id, valor, timestamp }
2. EstoqueReservado { pedido_id, itens, timestamp }
3. AprovacaoSolicitada { pedido_id, aprovador, timestamp }
4. PedidoAprovado { pedido_id, aprovador, timestamp }
Checkpointing para workflows com etapas longas (horas de processamento):
A cada 1000 registros processados em um ETL:
- Salvar checkpoint: "ultimo_id_processado = 50000"
- Em caso de falha, retomar a partir do checkpoint
- Evita reprocessamento completo
6. Escalabilidade e Concorrência em Workflows Longos
Particionamento por chave de negócio:
Particionamento por tenant_id:
- Tenant A: workflow-001 a workflow-100 -> Partição 1
- Tenant B: workflow-101 a workflow-200 -> Partição 2
- Cada partição executada em worker independente
Controle de concorrência com locks otimistas:
UPDATE workflow_instances
SET current_state = 'EM_APROVACAO', version = version + 1
WHERE id = 'abc-123' AND version = 3
-- Se outra transação já atualizou, o UPDATE falha (0 rows affected)
Uso de filas para desacoplamento:
Topico Kafka: "workflow.etapas"
- Producer: Orquestrador publica "etapa.concluida"
- Consumer: Worker especializado processa próxima etapa
- Garantia: pelo menos uma vez (idempotência necessária)
7. Monitoramento e Observabilidade de Processos Longos
Métricas essenciais:
# Prometheus metrics
workflow_cycle_time_seconds{workflow_type="aprovacao_pedido"}
workflow_completion_rate{status="sucesso"}
workflow_step_failures_total{step="pagamento"}
workflow_stuck_instances{timeout_hours="48"}
Logs estruturados com correlation ID:
{
"correlation_id": "wf-abc-123",
"timestamp": "2025-01-15T10:30:00Z",
"workflow_type": "aprovacao_pedido",
"current_state": "EM_APROVACAO",
"event": "timeout_atingido",
"duration_ms": 172800000,
"tenant": "cliente_x"
}
Alertas críticos:
- Workflows parados por mais de 24h sem progresso
- Taxa de falhas em etapa específica > 10%
- DLQ acumulando mais de 100 itens
8. Padrões de Implementação com Exemplos Práticos
Exemplo de workflow de aprovação com timeout usando Temporal:
// Definição do workflow
Workflow "AprovacaoPedido":
1. Receber pedido {id, valor, usuario}
2. Validar dados do pedido (2s timeout)
3. Se valor > 10000:
Enviar para aprovacao gerencial
Aguardar sinal "aprovado" ou "rejeitado" (48h timeout)
Se timeout -> estado EXPIRADO
4. Processar pagamento (3 retentativas com backoff)
5. Notificar cliente (fire-and-forget)
6. Retornar status final
// Atividade compensatória (saga)
Se pagamento falhar apos 3 tentativas:
- Reverter reserva de estoque
- Registrar na DLQ
- Notificar administrador
Versionamento de definições de workflow:
Workflow v1.0 (2024-01):
- Estados: [PENDENTE, EM_APROVACAO, APROVADO, REJEITADO]
Workflow v2.0 (2025-01):
- Estados: [PENDENTE, EM_APROVACAO, APROVADO_GERENCIA, APROVADO_DIRETORIA, REJEITADO, EXPIRADO]
- Migracao: Instancias v1.0 continuam no fluxo antigo
- Novas instancias usam v2.0
- Compatibilidade reversa mantida por 6 meses
Estratégia de schema evolution:
- Nunca remover estados existentes sem depreciação gradual
- Adicionar novos estados como transições opcionais
- Manter histórico de versões do workflow instance
Referências
- Temporal.io Documentation - Workflow Patterns — Documentação oficial sobre padrões de workflow para processos longos, incluindo retentativas, sagas e timeouts
- Camunda BPMN 2.0 Specification — Guia completo de modelagem de processos com máquinas de estados e orquestração
- Microsoft Azure - Saga Pattern — Artigo técnico sobre implementação de sagas para compensação em workflows distribuídos
- Apache Kafka - Event Sourcing Pattern — Documentação oficial sobre event sourcing para rastreamento de estado em workflows longos
- AWS - Designing Distributed Workflows — Melhores práticas para projetar workflows escaláveis com Step Functions e monitoramento
- Martin Fowler - Event Sourcing — Artigo fundamental sobre event sourcing e sua aplicação em processos longos
- Uber Cadence - Workflow Patterns — Padrões de resiliência e checkpointing para workflows de longa duração