No amplo universo de Sagas em microserviços, o Time Travel Saga combina comunicação síncrona, consistência eventual e coordenação por coreografia. Neste artigo, apresentamos como esse padrão funciona, seus principais componentes, exemplos de aplicação e considerações de projeto.
1. Fundamentação
- Comunicação Síncrona
- Cada serviço chama diretamente o próximo (ou um conjunto de serviços), aguardando resposta antes de prosseguir.
- O fluxo faz uso de endpoints ou chamadas bloqueantes em vez de trocar mensagens assíncronas.
- Consistência Eventual
- As atualizações ocorrem localmente em cada serviço, e se acontecer uma falha em etapas futuras, são aplicadas compensações que desfazem operações anteriores.
- Isso implica que o sistema pode ficar momentaneamente em estados intermediários, convergindo à consistência apenas depois das compensações.
- Coreografia
- Não há um orquestrador central que dite a ordem exata dos passos. Em vez disso, cada serviço determina quem chama em seguida ou como sinalizar falhas, reagindo a resultados de modo distribuído.
- As decisões de prosseguir ou reverter se baseiam em regras e protocolos que cada serviço deve conhecer.
A referência a “Time Travel” sugere a ideia de que, ao detectar falhas futuras, os serviços podem “voltar no tempo” para corrigir (compensar) estados anteriores, porém mantendo a comunicação ponto a ponto e permitindo que cada participante conheça parcialmente o fluxo.
2. Características Essenciais
2.1 Ausência de Orquestrador Central
- Em vez de um único componente responsável por gerenciar a sequência das etapas, cada serviço chama o próximo de forma síncrona.
- Caso haja falha, o serviço que detectou o erro pode iniciar uma série de compensações em si mesmo ou em serviços anteriores, retornando sinais ou chamando endpoints específicos de rollback.
2.2 Chamadas Diretas (Síncronas)
- Cada etapa bloqueia até receber resposta do serviço seguinte ou do serviço anterior (caso esteja revertendo).
- Requer definição de tempo de espera (timeout) e forma de lidar com indisponibilidade. Se o próximo serviço demora demais, o serviço atual pode interpretar como falha e acionar compensações, gerando novamente a lógica de “voltar no tempo”.
2.3 Consistência Via “Confirma e Compensa”
- Ao concluir cada passo, o serviço efetiva as mudanças localmente.
- Se um próximo passo falhar, ocorre a compensação do que já foi feito, levando algum tempo para que todos os serviços afetados se alinhem e retornem ao estado coerente.
3. Funcionamento Passo a Passo (Exemplo)
- Serviço A recebe a solicitação inicial de um cliente. Executa sua transação local e, em caso de sucesso, chama o Serviço B de forma síncrona.
- Serviço B processa. Se a operação der certo, chama o Serviço C. Se falhar, envia de volta um sinal de erro para A (ou diretamente chama um endpoint de compensação em A).
- Serviço C é chamado por B e faz seu trabalho. Se der sucesso, finaliza o processo ou chama outro serviço. Se falhar, sinaliza B para reverter sua etapa. B, por sua vez, sinaliza A para reverter a dele, e assim por diante.
sequenceDiagram
autonumber
participant A as Serviço A
participant B as Serviço B
participant C as Serviço C
A->>B: Chamada Síncrona (Etapa 1)
B-->>A: Resposta (OK ou Falha)
alt Falha em B
A->>A: Aplicar compensação local
else Sucesso
B->>C: Chamada Síncrona (Etapa 2)
C-->>B: Resposta (OK ou Falha)
alt Falha em C
B->>B: Compensar Etapa em B
B->>A: Notificar A sobre rollback
A->>A: Compensar etapa local
else Sucesso
B->>B: Etapa concluída
A->>A: Fluxo finalizado
end
end
Nesse fluxo, não há um orquestrador central, mas sim uma coreografia síncrona: cada serviço sabe a quem chamar e como disparar compensações.
4. Cenários Possíveis de Aplicação
4.1 Operações em Pequenos Conjuntos de Serviços
Situações em que há 2 ou 3 serviços envolvidos, e cada um precisa chamar o próximo de forma direta. O fluxo não é muito longo, permitindo gerenciar o retorno de erro e a compensação sem grande complexidade.
4.2 Processos que Admitam Latência Potencial nas Compensações
Como as correções (rollbacks) acontecem em cadeia, é necessário que a aplicação tolere períodos de inconsistência. Por exemplo, se B falhar depois que A já executou sua operação, a compensação de A pode levar algum tempo até ser concluída, e nesse ínterim o sistema apresenta um estado intermediário.
5. Desafios e Pontos de Atenção
5.1 Coordenação Distribuída
Cada serviço precisa saber não apenas quem invocar na sequência, mas também como sinalizar erros e acionar compensações. Esse conhecimento de “quem chama quem” pode elevar a complexidade de manutenção caso o número de serviços aumente.
5.2 Rastreamento de Fluxo
Como não existe um orquestrador único, o acompanhamento do estado global do processo depende de logging e correlação entre cada chamada síncrona. Ferramentas de trace distribuído (por exemplo, Jaeger, Zipkin) ajudam a entender em que etapa ocorreu a falha.
5.3 Timeouts e Falhas de Rede
Em comunicação síncrona, se o próximo serviço está indisponível ou leva muito tempo para responder, o serviço atual pode considerar isso como falha e iniciar compensações. Essa decisão precisa de critérios bem definidos (ex.: tempo limite, contagem de retentativas).
6. Vantagens Potenciais
- Baixo Overhead de Infraestrutura: Não exige um orquestrador central ou mensageria complexa.
- Simplicidade de Execução Passo-a-Passo: Cada serviço chama o seguinte, aguardando finalização antes de seguir.
- Flexibilidade de Compensação: Cada serviço gerencia sua própria reversão, recebendo notificações diretamente e aplicando o rollback local.
7. Conclusão
O Time Travel Saga (Síncrona, Consistência Eventual, Coreografada) descreve um padrão onde:
- Comunicação: Cada etapa chama a próxima de forma bloqueante,
- Consistência: Fica a cargo do “confirma e compensa”, permitindo estados intermediários até que os rollbacks se concretizem,
- Coordenação: É distribuída, sem orquestrador único, lembrando a ideia de serviços “passando a bola” entre si e retrocedendo no tempo caso algo dê errado em um passo posterior.
Esse modelo pode ser útil em cenários com um número moderado de participantes, onde a lógica de fluxo é clara para cada serviço e onde não se exige atomicidade total. A aplicação dessa abordagem requer cuidado ao definir rotas de compensação, tempos de espera e mecanismos de rastreamento do estado em cada serviço, de modo a garantir a confiabilidade do processo como um todo.