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

Como funciona

Durable Workflow usa os jobs em fila do Laravel e a persistência baseada em eventos para criar corrotinas duráveis. Funções baseadas em Fibers suspendem os workflows e permitem reconstruir sua execução por replay.

Runtime​

Um workflow é uma classe cujo método handle() chama funções como activity(), await(), timer(), sideEffect(), child() e all([...]) diretamente, em código sequencial. Cada chamada suspende o workflow até que a etapa durável correspondente termine. A execução então retoma de onde parou, com o resultado registrado.

Cada etapa produz um evento de histórico durável. Sempre que o workflow é reativado, o mecanismo faz replay desse histórico e reconstrói o estado a partir dos eventos antes de executar a próxima etapa pendente. Isso permite sobreviver a reinicializações de workers, implantações e falhas de máquinas sem perder o ponto de execução.

WorkflowStub::make() reserva um identificador público de instância. Iniciar o workflow cria a primeira execução e a primeira tarefa de workflow. Cada execução tem seu próprio identificador. Operações como signal(), cancel() e terminate() atuam na execução atual da instância.

Event sourcing​

Event sourcing reconstrói o estado atual a partir de uma sequência de eventos salvos, em vez de salvar o estado diretamente. Isso fornece um histórico completo dos eventos de execução e permite retomar um workflow se o worker falhar.

Corrotinas​

Corrotinas são funções cuja execução pode ser suspensa e retomada. Os pontos de suspensão duráveis são expressos por chamadas diretas a funções baseadas em Fibers, como activity(), await(), timer() e sideEffect().

O código do workflow fica em handle(), um método comum que chama essas funções diretamente. O runtime primeiro verifica se a etapa já terminou de forma durável. Se terminou, devolve o resultado registrado no histórico, sem executar a etapa outra vez. Caso contrário, coloca a próxima atividade, temporizador ou tarefa filha na fila e suspende o workflow até que a etapa termine ou falhe.

Atividades​

Um workflow coordena várias atividades e seus resultados. A execução do workflow se alterna com as etapas duráveis que ele agenda: ao chegar a uma chamada de atividade, o workflow suspende a execução até a atividade terminar e então continua de onde parou.

Se um worker de workflow falhar, o replay dos eventos confirmados reconstrói o estado atual. O workflow pode continuar de onde parou, com as mesmas entradas e saídas, preservando o determinismo. Uma falha não tratada no workflow torna a execução terminal. O replay não tenta novamente uma execução que já falhou.

Na v2, atividades comuns são trabalho durável em fila. As atividades locais executam tarefas curtas no processo do worker de workflow, preservando o histórico durável e as regras de novas tentativas. Atividades comuns podem executar em qualquer worker compatível. As sessões de workers adicionam um lease explícito quando uma sequência de atividades precisa do mesmo recurso local de um worker. Para registrar um valor uma única vez, de forma segura para replay e sem colocar uma atividade na fila, use sideEffect(...). Veja o contrato completo em Modelo de execução de atividades.

Garantias de execução​

O código do workflow e o código da atividade têm regras diferentes para repetição:

  • O código do workflow passa por replay. A reentrega de uma tarefa de workflow reconstrói o estado a partir do histórico durável e executa novamente o código determinístico de orquestração. O replay não repete efeitos externos já registrados.
  • Atividades são trabalho em fila executado pelo menos uma vez. Uma atividade lógica pode passar por novas tentativas, ser reentregue após a expiração de um lease ou ser observada novamente após a perda de um worker. Entregas duplicadas são uma condição normal em sistemas distribuídos.
  • A identidade da atividade é durável. activity_execution_id identifica uma execução lógica de atividade ao longo de novas tentativas e reentregas. activity_attempt_id identifica uma tentativa individual. Use activity_execution_id como chave padrão de idempotência no sistema remoto. Use activity_attempt_id apenas quando esse sistema precisa de correlação por tentativa.

Veja o contrato completo da v2 em Garantias de execução e idempotência, Modelo de execução de atividades e Falhas e recuperação.

Filas​

Jobs em fila são tarefas de segundo plano que executam mais tarde. O Laravel oferece filas com Amazon SQS, Redis ou um banco de dados relacional. Workflows e atividades são jobs em fila, com comportamentos diferentes. Um workflow é despachado várias vezes durante a operação normal: executa, despacha uma ou mais atividades e encerra seu job até que elas terminem. Uma atividade é uma tarefa em fila executada pelo menos uma vez. O caso comum é uma tentativa bem-sucedida, mas novas tentativas, expiração de leases ou perda de um worker podem causar a reentrega da mesma execução lógica de atividade.

Exemplo​

use Workflow\V2\Workflow;
use function Workflow\V2\{activity, all};

class MyWorkflow extends Workflow
{
public function handle(): array
{
return [
activity(TestActivity::class),
activity(TestOtherActivity::class),
all([
fn () => activity(TestParallelActivity::class),
fn () => activity(TestParallelOtherActivity::class),
]),
];
}
}

Diagrama de sequência​

Este diagrama mostra a progressão de um workflow por uma série de atividades, tanto em sequência quanto em paralelo.

Diagrama de sequência do workflow
Diagrama de sequência do workflow
  1. O workflow começa ao ser despachado como um job em fila.
  2. A primeira atividade, TestActivity, é despachada como um job em fila. O job do workflow então encerra. Quando TestActivity termina, salva o resultado no banco de dados e despacha o workflow novamente.
  3. O workflow entra no ciclo de replay do event sourcing. Ele consulta os eventos no banco de dados para reconstruir o estado atual. Isso é necessário porque o workflow não mantém um processo em execução contínua. Seu job encerra enquanto as atividades executam e é despachado novamente quando elas terminam.
  4. Após o replay dos eventos, o workflow continua para TestOtherActivity e a despacha como um job em fila. Quando essa atividade termina, salva o resultado no banco de dados e despacha o workflow novamente.
  5. O workflow faz outro replay dos eventos para reconstruir o estado atual.
  6. Em seguida, o workflow inicia duas atividades em paralelo, TestParallelActivity e TestParallelOtherActivity. Ambas são despachadas. Quando terminam, salvam seus resultados no banco de dados e devolvem o controle ao workflow.
  7. Por fim, o workflow faz replay dos eventos uma última vez para reconstruir o estado atual e concluir a execução.

Determinismo​

Como o histórico passa por replay sempre que o workflow é reativado, seu código deve produzir os mesmos comandos para o mesmo histórico. Veja Restrições para as regras de código e os recursos que Durable Workflow fornece, como Workflow::now() em Workflow\V2\Workflow, sideEffect() e getVersion(), quando o código seria não determinístico.