Pular para o conteúdo

Workflows

Workflows são operações duráveis e de longa duração que sobrevivem a crashes e reinicializações. Eles fornecem garantias de confiabilidade para processos de negócio críticos como pagamentos, cumprimento de pedidos e aprovações de múltiplas etapas.

Funções são efêmeras — se o host falha, o trabalho em andamento é perdido. Workflows persistem seu estado:

AspectoFunçõesWorkflows
EstadoEm memóriaPersistido
CrashTrabalho perdidoRetoma
DuraçãoSegundos a minutosHoras a meses
ConclusãoMelhor esforçoGarantida

O código de workflow se parece com código Lua regular:

local funcs = require("funcs")
local time = require("time")
local result = funcs.call("app.api:charge_card", payment)
time.sleep("24h")
local status = funcs.call("app.api:check_status", result.id)
if status == "failed" then
funcs.call("app.api:refund", result.id)
end

O motor de workflow intercepta chamadas e registra resultados. Se o processo falha, a execução é reproduzida do histórico — mesmo código, mesmos resultados.

O Wippy trata o determinismo automaticamente. Operações como funcs.call(), time.sleep(), uuid.v4(), e time.now() são interceptadas e seus resultados registrados. No replay, valores registrados são retornados ao invés de re-executar.

Compense em caso de falha:

local funcs = require("funcs")
local inventory = funcs.call("app.inventory:reserve", items)
if inventory.error then
return nil, inventory.error
end
local payment = funcs.call("app.payments:charge", amount)
if payment.error then
funcs.call("app.inventory:release", inventory.id)
return nil, payment.error
end
local shipping = funcs.call("app.shipping:create", order)
if shipping.error then
funcs.call("app.payments:refund", payment.id)
funcs.call("app.inventory:release", inventory.id)
return nil, shipping.error
end
return {inventory = inventory, payment = payment, shipping = shipping}

Aguarde eventos externos (decisões de aprovação, webhooks, ações do usuário):

local funcs = require("funcs")
funcs.call("app.approvals:submit", request)
local inbox = process.inbox()
local msg = inbox:receive() -- bloqueia até o sinal chegar
if msg.approved then
funcs.call("app.orders:fulfill", request.order_id)
else
funcs.call("app.notifications:send_rejection", request)
end
Caso de UsoEscolha
Tratamento de requisição HTTPFunções
Transformação de dadosFunções
Jobs em segundo planoProcessos
Estado de sessão de usuárioProcessos
Mensagens em tempo realProcessos
Processamento de pagamentoWorkflows
Cumprimento de pedidosWorkflows
Aprovações de múltiplos diasWorkflows

Workflows são criados da mesma forma que processos — usando process.spawn() com um host diferente:

-- Criar workflow no worker temporal
local pid = process.spawn("app.workflows:order_processor", "app:temporal_worker", order_data)
-- Enviar sinais para o workflow
process.send(pid, "update", {status = "approved"})

Da perspectiva do chamador, a API é idêntica. A diferença é o host: workflows executam em um temporal.worker ao invés de um process.host.

Quando um workflow cria filhos via process.spawn(), eles se tornam workflows filhos no mesmo provedor, mantendo as garantias de durabilidade.

Processos podem executar como serviços supervisionados usando process.service:

# Definição do processo
- name: session_handler
kind: process.lua
source: file://session_handler.lua
method: main
# Serviço supervisionado encapsulando o processo
- name: session_manager
kind: process.service
process: app:session_handler
host: app:processes
lifecycle:
auto_start: true
restart:
max_attempts: 10

Workflows não usam árvores de supervisão — eles são automaticamente gerenciados pelo provedor de workflow (Temporal). O provedor trata persistência, retries e recuperação.

Definição de processo (criado dinamicamente):

- name: order_processor
kind: workflow.lua
source: file://order_processor.lua
method: main
modules:
- funcs
- time

Provedor de workflow:

- name: temporal_worker
kind: temporal.worker
client: app:temporal_client
task_queue: "orders"
lifecycle:
auto_start: true

Veja Temporal para infraestrutura de workflow em produção.