Todo mundo quer atualizações em tempo real até perceber que "rápido" e "correto" não são a mesma coisa. Em um sistema distribuído, os eventos podem viajar à velocidade da luz e ainda assim chegar na ordem errada. WebSockets caem e reconectam. Brokers de mensagens reenviam pacotes. Workers de segundo plano competem contra cancelamentos por timeout. O resultado? Um cliente pode ver o evento 42, depois o evento 40, e então um snapshot alegando que o sistema já está no evento 45. Se você está construindo fluxos de trabalho de agentes de longa duração, esse caos não é um caso de borda. É a base. Corrija a ordem dos seus eventos antes de se preocupar em economizar milissegundos na entrega.
A Realidade Caótica do "Tempo Real"
O tempo real é uma propriedade de transporte. Ele descreve a rapidez com que um pacote se move através de um fio, não se a história que ele conta faz sentido. Tarefas de longa duração amplificam cada inconsistência porque se estendem ao longo do tempo. Um trabalho de treinamento de modelo, um fluxo de aprovação de múltiplas etapas ou um pipeline de renderização de vídeo podem emitir dezenas de eventos ao longo de minutos ou horas. Durante esse intervalo, qualquer coisa pode dar errado.
Um broker pode tentar reenviar uma mensagem porque um reconhecimento (acknowledgement) foi perdido. Um load balancer pode rotear dois eventos por caminhos de rede diferentes, fazendo com que o mais novo chegue primeiro. Um processo worker pode morrer após escrever no banco de dados, mas antes de publicar o evento de sucesso, apenas para um segundo worker assumir a tarefa e emitir seu próprio progresso. Se o seu frontend assume que a mensagem mais recente é a mensagem mais verdadeira, ele pintará um estado que nunca existiu. Os usuários verão um selo de "concluído" oscilar de volta para "processando" ou, pior, uma tarefa cancelada subitamente ressurgir. Velocidade sem ordenação é apenas confusão com uma taxa de quadros mais alta.
Números de Sequência São o Relógio Real
A solução são números de sequência estritos e monotônicos gerados pelo produtor. Cada operação que altera o estado recebe um número que aumenta exatamente em um, sem lacunas e sem rollbacks. Esse número deve ser persistido na mesma transação que o próprio evento. Se a linha do banco de dados for atualizada, mas o commit da sequência falhar, você deve fazer o rollback de ambos. Isso mantém a linha do tempo lógica atômica com a mudança de estado.
IDs de evento ainda são úteis, mas resolvem um problema diferente. Um ID de evento identifica um payload específico para que você possa deduplicá-lo quando o broker entregar a mesma mensagem duas vezes. Um número de sequência, por outro lado, diz onde esse payload pertence na cadeia causal. Ele expõe lacunas. Ele expõe a ordenação. Um timestamp não faz nenhum dos dois. Relógios derivam, o NTP volta no tempo e máquinas virtuais pausam. Use timestamps apenas para fins de exibição, algo como "Iniciado há 3 minutos", e nunca como uma chave de ordenação para lógica de negócio.
Como o Cliente Deve Lidar com o Fluxo
Assim que o produtor garante uma sequência monotônica, o consumidor recebe regras simples e rígidas. Se um número de sequência de entrada for menor ou igual ao último número aplicado, descarte-o. Ele é um duplicado ou um atrasado desatualizado. Se a sequência for exatamente um número maior que o último número aplicado, aplique-o imediatamente. Esse é o caminho feliz. Se a sequência saltar para frente, digamos que você esperava o 12, mas recebeu o 15, algo está faltando. Armazene o novo evento em buffer e peça ao servidor um replay começando da próxima sequência esperada. Não adivinhe. Não pule etapas esperando que a lacuna não importe.
Estados terminais devem ser tratados como irrevogáveis. Uma vez que uma tarefa é marcada como concluída, falhou ou cancelada, o cliente deve rejeitar quaisquer mudanças de estado subsequentes para essa operação. Isso parece óbvio até que você lide com
