Pular para o conteúdo principal
Versão: 2.0

Garantias de execução e idempotência

Durable Workflow v2 estabelece uma fronteira clara entre o replay do workflow e a execução de atividades:

  • O código do workflow passa por replay a partir do histórico confirmado e deve ser determinístico.
  • O código da atividade realiza efeitos externos e executa pelo menos uma vez.
  • A camada de histórico durável registra os resultados confirmados de workflows e atividades exatamente uma vez para um mesmo identificador durável, mesmo quando o transporte entrega o trabalho mais de uma vez.

Essas garantias permitem sobreviver a reinicializações de workers, expiração de leases, reentrega de filas e implantações graduais sem perder o ponto da execução.

Replay não é uma nova tentativa​

As tarefas de workflow reconstroem o estado por replay do histórico confirmado e então decidem o próximo passo. O replay executa novamente o corpo do workflow, mas não executa novamente atividades, reenvia sinais nem repete efeitos já registrados no histórico.

Por isso, o código de orquestração deve ser determinístico. Use recursos seguros para workflows, como Workflow::now(), sideEffect(...), consultas, atualizações, resultados de atividades, memos e atributos de busca quando precisar atravessar a fronteira durável.

Atividades executam pelo menos uma vez​

Como as atividades realizam efeitos externos, seu contrato é diferente:

  • Uma tentativa de atividade pode ser adquirida mais de uma vez.
  • A expiração de um lease pode provocar a reentrega a outro worker.
  • Um worker pode concluir uma operação externa, perder seu lease e enviar o resultado depois.
  • Uma nova tentativa agenda outra tentativa durável para a mesma execução lógica de atividade.

Observar o mesmo trabalho mais de uma vez faz parte do contrato. Quem desenvolve a aplicação deve tornar o corpo da atividade, ou o sistema remoto que ela chama, seguro para repetição.

Veja Restrições das atividades para orientações de código e Falhas e recuperação para o comportamento de recuperação disponível ao operador.

O que ocorre exatamente uma vez​

Durable Workflow não promete que um processo de worker receba trabalho com efeitos externos apenas uma vez. Ele garante que os fatos duráveis confirmados são a fonte de verdade e não se duplicam para um mesmo identificador durável.

Na prática:

  • Uma decisão confirmada do workflow é persistida uma vez no histórico tipado para o identificador durável de comando ou etapa que representa.
  • Um resultado terminal confirmado de uma tentativa de atividade é persistido uma vez para seu activity_attempt_id.
  • O replay lê esses fatos confirmados e reconstrói o estado do workflow, sem repetir o trabalho externo.

O modelo central é:

  • Transporte e workers operam pelo menos uma vez.
  • O histórico durável confirmado registra os fatos exatamente uma vez por identificador durável.

Expiração de leases e reentrega​

A expiração de um lease é um caminho normal de recuperação em sistemas distribuídos:

  • Uma tarefa adquirida tem um proprietário de lease e um horário de expiração.
  • Se o lease expirar antes de o worker relatar progresso ou conclusão, a tarefa fica disponível para reentrega.
  • Outro worker pode adquirir o mesmo trabalho lógico.

A reentrega não significa que o mecanismo esqueceu o que já foi confirmado. Ela recupera a execução diante da incerteza na camada de worker ou transporte.

Ao investigar sintomas de execução duplicada, separe duas perguntas:

  1. O efeito externo aconteceu mais de uma vez?
  2. O estado durável registrou mais de um resultado confirmado para o mesmo identificador durável?

A primeira questão exige atividades idempotentes. A segunda faz parte do contrato do mecanismo.

Identificadores padrão de idempotência​

Estes identificadores são referências estáveis para deduplicar trabalho:

IdentificadorO que identificaUso comum
workflow_instance_idUma instância pública de workflowTratar inícios duplicados e identificar a execução no domínio da aplicação
workflow_run_idUma execução durável específicaFixar a execução selecionada para consultas, exportação ou diagnóstico
workflow_command_idUm comando externo que modifica estadoDeduplicar novas tentativas de solicitações do cliente
activity_execution_idUma execução lógica de atividade ao longo de novas tentativasChave padrão de idempotência para efeitos externos
activity_attempt_idUma tentativa específica dessa atividadeCorrelacionar tentativas quando o sistema remoto precisa distingui-las
schedule_idUma definição de agendamentoDeduplicar operações de propriedade e identidade de disparos
idempotencyKey do fluxo de mensagensUm envio lógico de mensagem sujeito a novas tentativasEvitar a ingestão duplicada quando o remetente tenta novamente

Na dúvida, use activity_execution_id como chave padrão de idempotência de uma operação externa. Use activity_attempt_id apenas quando o destino externo realmente precisar distinguir cada tentativa.

use Workflow\V2\Activity;

final class ChargeCard extends Activity
{
public function handle(array $payload): string
{
return app(PaymentGateway::class)->charge(
$payload,
idempotencyKey: $this->activityId(),
attemptCorrelation: $this->attemptId(),
);
}
}

O que a aplicação precisa tornar idempotente​

Você não precisa tornar o próprio replay idempotente. O framework reconstrói o estado a partir do histórico confirmado.

Você precisa tornar seguros para repetição os efeitos externos, como:

  • chamadas de pagamento ou cobrança
  • e-mails, mensagens de texto e webhooks
  • gravações em outro banco de dados ou serviço
  • criação ou upload de arquivos
  • qualquer comando que crie ou modifique estado fora do histórico do workflow

Abordagens comuns:

  • Passe uma chave de idempotência à API remota.
  • Grave em um recurso de destino determinístico, como uma chave de objeto conhecida.
  • Use um upsert ou uma transação com um identificador durável como chave.
  • Torne a ação naturalmente repetível, para que a segunda chamada não altere nada.

Orientações para operação​

Ao diagnosticar uma execução no Waterline, na CLI ou nos logs do Server:

  • Considere normal observar uma atividade novamente após a expiração de um lease, até que o resultado durável da tentativa indique um problema.
  • Considere relatos tardios de conclusão ou falha como uma disputa que o mecanismo resolve. Eles não provam que o efeito externo deixou de acontecer.
  • Trate o replay de uma tarefa de workflow como recuperação, e não como uma nova tentativa do workflow inteiro.
  • Investigue workers compatíveis ausentes, leases presos ou reparos repetidos como sinais operacionais. Eles não justificam repetir efeitos externos no corpo do workflow.

A distinção essencial para a operação é entre incerteza do transporte e resultado durável. Durable Workflow expõe ambos para que você possa distingui-los.