Os trabalhos assíncronos permitem desacoplar importações, sincronizações, notificações, geração de documentos e integrações. No entanto, o fato de um consumidor ter processado uma mensagem não demonstra necessariamente que o resultado de negócio esteja correto. Um sucesso pode ter sido registrado antes de confirmar um efeito externo, pode ter ocorrido uma falha entre duas etapas ou a mesma operação pode ter sido executada mais de uma vez.
A reconciliação de trabalhos assíncronos em PHP cobre essa diferença: compara o que o sistema esperava alcançar com a evidência do que ocorreu, detecta ausências ou discrepâncias e aciona uma correção controlada. Ela não substitui a fila, as retentativas nem a idempotência; ela as complementa com uma verificação independente.
Uma execução técnica não equivale a um resultado de negócio

Uma tarefa pode terminar sem uma exceção e, ainda assim, deixar um processo incompleto. Por exemplo, uma aplicação cria uma solicitação de sincronização, o consumidor chama uma API externa e recebe uma resposta inconclusiva devido a uma interrupção de rede. Se ele tentar novamente sem uma chave idempotente, poderá criar uma duplicata. Se assumir o sucesso, poderá deixar o registro sem sincronizar.
Também não se deve presumir uma semântica de entrega específica da infraestrutura de mensageria. A possibilidade de redeliveries e execuções duplicadas depende do broker, de sua configuração de persistência, dos reconhecimentos, do comportamento do consumidor e das falhas que ocorrerem. O projeto deve verificar essas propriedades na tecnologia escolhida e, quando duplicatas ou reordenações puderem ocorrer, tolerá-las explicitamente.
A pergunta operacional não é apenas «a mensagem foi consumida?», mas «posso demonstrar que o efeito esperado existe, uma única vez quando aplicável, e com os dados corretos?». Essa demonstração requer uma fonte de evidência: uma resposta consultável do sistema externo, um identificador remoto persistido, um documento armazenado ou uma alteração de estado confirmada.
Retentativas, idempotência e reconciliação: responsabilidades distintas
As retentativas tratam erros transitórios: indisponibilidade temporária, limites de uso, bloqueios breves ou problemas de rede. Convém definir limite de tentativas, atraso progressivo, classificação de erros e destino para mensagens que precisam de atenção. Tentar novamente indefinidamente pode ocultar um erro de dados ou agravar um incidente externo.
A idempotência torna seguro repetir uma operação. Ela pode ser obtida com um identificador estável da operação enviado a um provedor externo, uma restrição única no banco de dados ou uma verificação transacional anterior ao efeito. Isso não significa que o efeito tenha ocorrido: significa que uma repetição não deve multiplicá-lo.
A reconciliação busca operações pendentes, incompletas ou contraditórias e decide o que fazer com cada uma. Ela é especialmente necessária quando há efeitos externos, processos em lote, atualizações de vários sistemas ou comunicações cujo recebimento não pode ser comprovado apenas a partir da aplicação emissora.
- Use retentativas para tentar novamente falhas classificadas como transitórias.
- Use idempotência para impedir que retentativas ou redeliveries dupliquem efeitos.
- Use reconciliação para verificar o estado final e reparar diferenças detectadas.
Modelar a operação e preservar evidência verificável
Um projeto sustentável separa três conceitos. O trabalho solicitado representa a intenção, por exemplo, «sincronizar o pedido 452». O efeito esperado define o resultado observável: «o sistema externo contém o pedido com a versão 7». A confirmação armazena a evidência de que esse resultado existe: identificador remoto, versão, marca temporal, resposta validada ou resultado de uma consulta posterior.
Antes de publicar uma mensagem, crie um registro de execução em um banco de dados durável. Se a aplicação modificar dados próprios e publicar uma mensagem, considere o padrão outbox: salve a alteração de negócio e o evento pendente na mesma transação, e delegue a publicação a um processo posterior. Assim, reduz-se o risco de confirmar a alteração local e perder a mensagem, ou publicar uma mensagem para uma alteração que foi revertida.
O registro deve incluir, no mínimo:
- operation_id imutável e único, usado para correlacionar mensagens, logs e chamadas externas.
- Tipo de operação, entidade afetada e versão ou hash do conteúdo esperado.
- Estado atual, número de tentativas, próxima tentativa permitida e marcas temporais.
- Chave idempotente e, se existir, identificador do recurso remoto.
- Evidência resumida e referências seguras a respostas ou erros, sem registrar segredos nem dados pessoais desnecessários.
- Motivo de encerramento, compensação, descarte ou escalonamento para revisão humana.
Defina transições explícitas, por exemplo: pending, processing, awaiting_confirmation, confirmed, retry_scheduled, manual_review, compensated e not_applicable. Cada transição deve ter um responsável e uma condição verificável. Uma atualização condicional, como passar para processing apenas se o estado anterior for pending, reduz condições de corrida entre consumidores.
Construir o processo de reconciliação
A reconciliação pode ser executada por meio de um comando PHP agendado, um worker dedicado ou um fluxo operacional. Ela deve trabalhar com janelas temporais: não examine operações criadas há segundos se a integração externa normalmente leva vários minutos. Defina a janela com dados reais de latência e revise-a ao alterar limites ou provedores.
Para cada operação elegível, compare fontes de verdade previamente definidas. A base local pode ser a autoridade sobre a intenção e a versão do dado; o sistema externo, sobre se recebeu ou criou o recurso. Quando não houver uma consulta confiável ao destino, a evidência pode ser uma confirmação assinada, um identificador do provedor ou uma verificação posterior por arquivo de resultado.
- Selecione operações não confirmadas que ultrapassem seu prazo esperado.
- Verifique se o efeito existe usando
operation_id, chave idempotente ou uma chave de negócio inequívoca. - Compare campos relevantes e versões, não apenas a existência do recurso.
- Classifique o caso como ausente, correto, divergente, ambíguo ou não aplicável.
- Execute a ação autorizada e registre a decisão com sua evidência.
Um resultado ambíguo não deve ser convertido automaticamente em reenfileiramento. Se uma chamada pode ter criado um recurso, mas não há como consultá-lo de forma confiável, tentar novamente poderá duplicar uma cobrança, uma notificação ou um documento. Nesses casos, bloqueie a ação automática e envie o caso para um painel de exceções com contexto suficiente para decidir.
Corrigir sem introduzir novos danos
A ação depende da discrepância e do custo de errar. Reenfileirar é adequado quando o efeito está ausente e a operação é idempotente. Compensar pode reverter um efeito incorreto por meio de uma operação de negócio explícita, não por uma exclusão técnica indiscriminada. Marcar para revisão é preferível diante de ambiguidade, conflito de versões ou consequências financeiras. Encerrar como não aplicável serve quando a entidade foi cancelada ou substituída conforme regras documentadas.
Os reparos manuais também devem deixar rastros: quem tomou a decisão, qual evidência consultou, qual ação aplicou e qual foi o resultado. Limite permissões e evite botões que executem uma operação sem mostrar a entidade, a versão, o destino e o risco de duplicação.
Observabilidade e testes que validam o projeto
Logs correlacionados por operation_id facilitam acompanhar uma operação entre web, workers e serviços externos. As métricas úteis não se limitam a exceções: meça a antiguidade das operações pendentes, a quantidade em revisão manual, a taxa de divergências, as retentativas por causa e o tempo até a confirmação. Os alertas devem ser disparados por acúmulo, antiguidade ou descumprimento de prazo, não por cada erro isolado.
Teste falhas representativas: falha após o efeito externo e antes de persistir a confirmação; execução duplicada; mensagem fora de ordem; reinicialização do worker; timeout com resultado remoto incerto; indisponibilidade prolongada; e alterações de versão enquanto uma operação continua pendente. O teste deve verificar tanto o estado final quanto a ausência de duplicatas e a qualidade da evidência armazenada.
Exemplo: sincronizar um registro com um sistema externo
Suponha que uma aplicação PHP sincronize um registro de cliente. Ao modificá-lo, ela cria a operação sync_customer com um identificador estável e a versão local esperada. O worker envia esses valores ao destino como chave idempotente. Se receber uma confirmação válida, persiste o identificador remoto e altera o estado para confirmed.
Se o timeout ocorrer após enviar a solicitação, o worker deixa a operação em awaiting_confirmation. O reconciliador consulta o destino pela chave idempotente. Se encontrar a mesma versão, confirma. Se não a encontrar, agenda um novo envio. Se encontrar uma versão diferente, marca o caso para revisão em vez de sobrescrever dados que poderiam ter sido modificados legitimamente no outro sistema.
Checklist para incorporar reconciliação sem reescrever o processo

- Faça o inventário dos trabalhos existentes e priorize os que produzem efeitos externos, afetam dinheiro, dados regulatórios ou processos difíceis de repetir.
- Para cada tipo, documente o efeito esperado, a fonte de verdade e a evidência que permitirá confirmá-lo.
- Verifique no broker e nos consumidores específicos o que ocorre diante de falhas, reconhecimentos tardios, persistência, redelivery e ordem das mensagens.
- Adicione um
operation_idestável e propague-o na mensagem, nos logs, nas chamadas externas e nos registros de estado. - Introduza uma tabela de operações com estados, tentativas, prazos, chave idempotente e evidência; comece em modo de observação, se necessário.
- Defina transições condicionais e uma política escrita para tentar novamente, confirmar, compensar, escalar ou encerrar como não aplicável.
- Implemente um reconciliador limitado a uma janela temporal e a um tipo de operação piloto.
- Valide com casos de duplicata, timeout ambíguo, falha entre etapas, reordenação e reinicialização antes de automatizar correções.
- Crie um painel ou consulta de exceções com antiguidade, entidade, evidência e ação recomendada.
- Revise periodicamente métricas, operações paralisadas e decisões manuais para ajustar prazos, regras e controles.
A adoção gradual permite melhorar a confiabilidade sem substituir toda a arquitetura: primeiro torne visíveis as operações incertas, depois confirme os resultados e, por fim, automatize apenas as correções cuja segurança possa demonstrar.



