Timers e Prazos
Timers modelam a passagem do tempo dentro de um processo: uma aprovação que expira, um SLA que
dispara um alerta, uma escalada automática. São sempre declarados como eventos de borda
(boundary events), anexados a um EXECUTABLE_TASK ou EXTERNAL_TASK via attachedToRef.
Um boleto fica válido até uma data de vencimento; passado esse prazo, ele simplesmente deixa de valer e o processo de cobrança segue por outro caminho — sem que ninguém precise ficar checando o relógio manualmente. A analogia cobre bem o timer interruptivo (o vencimento desvia o fluxo). Ela não cobre o timer não-interruptivo: um boleto não manda lembretes periódicos sozinho, mas o Kikwiflow pode disparar alertas repetidos — "faltam 3 dias", "faltam 3 horas" — sem invalidar nada, em paralelo à espera original.
Existem dois tipos, com efeitos bem diferentes sobre o nó ao qual estão anexados:
| Tipo | Dispara | Efeito sobre o nó pai |
|---|---|---|
BOUNDARY_INTERRUPTIVE_TIMER | Uma vez, em um instante calculado | Interrompe o nó pai — a espera original é cancelada e a execução desvia para a saída do timer |
BOUNDARY_NON_INTERRUPTIVE_TIMER | Repetidamente, segundo uma política de agendamento | Não interrompe o nó pai — dispara em paralelo (ex.: notificações periódicas de SLA) |
"E se o analista não decidir em 48h?"
No processo de abertura de conta, Aprovar
Abertura espera indefinidamente por padrão. Um timer interruptivo dá um prazo real a essa espera:
se o analista de crédito não registrar a decisao em 48 horas, a solicitação é recusada
automaticamente por SLA e o fluxo segue para o encerramento, em vez de ficar pendurado para
sempre.
{
"id": "timer-sla-aprovacao",
"type": "BOUNDARY_INTERRUPTIVE_TIMER",
"providerType": "STATIC",
"staticValue": "PT48H",
"attachedToRef": "EXTERNAL_E5F3809A",
"outgoing": [ { "targetNodeId": "END_RECUSADA_POR_SLA" } ]
}
O prazo-alvo é resolvido por uma entre três estratégias, via providerType:
providerType | Origem do valor | Campo relevante |
|---|---|---|
STATIC | Valor fixo no JSON | staticValue |
VARIABLE | Variável de processo já calculada | providerVariable |
BEAN | Bean Spring implementando DueDateProvider | providerBean |
DueDateProvider: prazos calculados em Java
Quando o prazo depende de uma regra de negócio — por exemplo, um cliente VIP tem um SLA de análise mais curto que os demais:
public interface DueDateProvider {
/** ISO-8601: duração ("PT1H") ou data absoluta ("2026-12-25T20:00:00Z") */
String resolve(EvaluationContext execution);
}
package com.empresa.processo.decision;
import io.kikwiflow.execution.api.context.EvaluationContext;
import io.kikwiflow.execution.api.provider.DueDateProvider;
import org.springframework.stereotype.Component;
@Component("slaAprovacaoBean")
public class SlaAprovacaoDueDateProvider implements DueDateProvider {
@Override
public String resolve(EvaluationContext execution) {
boolean vip = Boolean.TRUE.equals(execution.getVariableValue("clienteVip").orElse(false));
return vip ? "PT12H" : "PT48H";
}
}
O valor retornado — de staticValue, de uma variável, ou de um DueDateProvider — aceita
indistintamente uma duração ISO-8601 ("PT48H", somada ao instante atual) ou uma data
absoluta ISO-8601 ("2026-12-25T20:00:00Z"). Não é preciso declarar qual formato está sendo
usado; o motor tenta interpretar como data absoluta primeiro e, se falhar, como duração relativa.
Timer não-interruptivo: alertas periódicos
Use quando o timer só precisa produzir um sinal em paralelo, recorrentemente, sem afetar a tarefa original — por exemplo, lembrar o analista de crédito a cada 12 horas enquanto Aprovar Abertura segue pendente:
{
"id": "lembrete-aprovacao",
"type": "BOUNDARY_NON_INTERRUPTIVE_TIMER",
"attachedToRef": "EXTERNAL_E5F3809A",
"schedulePolicy": { "type": "RATE_DURATION", "expression": "PT12H" }
}
schedulePolicy.type aceita RATE_DURATION (repete a cada duração ISO-8601 declarada em
expression, indefinidamente) ou FIXED_DATES (uma lista de instantes ISO-8601 em fixedDates;
quando o último já passou, o ciclo termina naturalmente, sem reagendar).
"type": "CRON" por enquantoO suporte a expressões cron reais (* * * * *) ainda não está implementado — declarar type: "CRON"
hoje trata expression como uma duração ISO-8601, não como uma expressão cron, e provavelmente
falha ao fazer o parsing de uma expressão cron tradicional. Use RATE_DURATION explicitamente até
que o suporte a cron seja lançado.
Modelar no Craft
Selecione o nó Aprovar Abertura e, na paleta de eventos de borda, arraste um timer
interruptivo (SLA timeout) para a borda dele. Ligue a saída do timer ao encerramento por SLA.
Repita com um timer não-interruptivo para o lembrete — os dois convivem no mesmo nó sem
conflito. O Craft escreve o attachedToRef automaticamente.
Implementar
Só o modo providerType: BEAN exige código — a classe DueDateProvider acima, um @Component
nomeado igual ao providerBean. Os modos STATIC e VARIABLE não precisam de bean nenhum.
Operar no Monitor
Inicie uma instância e não complete Aprovar Abertura. No card da tarefa executável/agendada do Monitor, o timer aparece como Agendada, com a contagem regressiva até disparar. Quando o prazo vence, o Monitor mostra a espera sendo interrompida e o fluxo desviando para o encerramento por SLA — sem nenhuma ação manual. O timer não-interruptivo aparece disparando a cada 12h em paralelo, sem mexer no card de Aprovar Abertura.
📸 [ASSET NECESSÁRIO] Print do Monitor com uma instância parada em "Aprovar Abertura" e o painel lateral mostrando o timer de SLA de 48h como "Agendada", com a contagem regressiva visível. Incluir no documento de assets:
monitor-timer-sla-agendado.png
Quando usar / quando não usar
Use interruptivo quando o vencimento do prazo deve desviar o fluxo para outro caminho — como recusar por SLA uma aprovação parada há 48h.
Use não-interruptivo quando o vencimento apenas dispara um efeito colateral (notificação, alerta), sem alterar o caminho da tarefa original — como lembrar o analista a cada 12h.
Não use um timer para esperar por um evento externo com uma chave de negócio conhecida (um webhook, uma confirmação de outro sistema) — isso é correlação de eventos, não um prazo.
Próximo passo
Um timer que dispara sem que o negócio consiga tratar aquilo de forma limpa é, na prática, uma forma de erro esperado. Veja como modelar erros de negócio explicitamente em Tratando Erros de Negócio.