Tarefas Externas e Workers
Uma EXTERNAL_TASK modela um passo cuja conclusão não está sob controle direto do motor — uma
aprovação humana em uma tela, um callback assíncrono de um sistema externo, um evento que chega
horas ou dias depois. Diferente de uma EXECUTABLE_TASK, não há TaskHandler associado: o nó
simplesmente fica pendente até que algo, de fora, sinalize que ele terminou.
Você entrega a ficha, a escola confere os documentos — e então a ficha fica em uma pilha aguardando a assinatura da diretora. O processo não terminou. Não foi cancelado. Está parado em um ponto específico, aguardando uma ação externa. Quando a diretora assina, o processo avança para o próximo passo.
Uma tarefa externa no Kikwiflow funciona assim: a instância está ativa, persiste seu estado, e
aguarda uma chamada externa (pelo KikwiflowEngine, pela API REST ou por uma tela de operação) que a
sinalize para avançar.
Nenhum recurso de CPU é consumido enquanto espera — não há uma thread bloqueada, parada, contando os
segundos.
O exemplo desta página é uma etapa Aprovar Abertura num processo de abertura de conta: depois que o
score é calculado, o processo para ali, e não avança sozinho — nem em um segundo, nem em uma hora — até
que um analista de crédito revise o resultado e registre a decisao.
Declarar no .kikwi
No .kikwi (ou no Craft, como External Task), o nó não declara executor. O ator responsável — útil
para filtrar filas de trabalho — vai em extensionProperties. O motor não interpreta esse campo: ele não
impede que outra pessoa assuma ou conclua a tarefa. Se isso importa, a checagem é da sua aplicação (ver
Quem pode assumir e concluir uma tarefa externa).
{
"id": "APROVAR_ABERTURA",
"name": "Aprovar Abertura",
"type": "EXTERNAL_TASK",
"extensionProperties": { "actor": "analista_credito" },
"outgoing": [ { "targetNodeId": "END_CONTA_ABERTA" } ]
}
Não há campo executor — não há bean Spring a resolver. O nó apenas cria um registro de tarefa
pendente e aguarda.
Ciclo de vida
- Criada — quando o fluxo alcança o nó, uma
ExternalTaskpendente é registrada. claim(opcional) — um worker ou operador reivindica a tarefa para si, evitando que outra pessoa processe o mesmo item ao mesmo tempo.complete— alguém (um operador numa tela, um endpoint da sua aplicação, um job) sinaliza que a tarefa terminou, opcionalmente entregando variáveis de processo. O motor então continua o fluxo a partir dali, mesclando essas variáveis na instância — de forma síncrona, até o próximo ponto decommitBeforeou o fim do processo.
Completar a tarefa
De dentro da própria aplicação — um controller seu, um listener de evento, um callback de outro sistema —
injete KikwiflowEngine e chame completeExternalTask:
package com.empresa.processo.aprovacao;
import io.kikwiflow.KikwiflowEngine;
import io.kikwiflow.model.execution.ProcessVariable;
import io.kikwiflow.model.security.IdentityContext;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class AprovacaoService {
private final KikwiflowEngine kikwiflowEngine;
public AprovacaoService(KikwiflowEngine kikwiflowEngine) {
this.kikwiflowEngine = kikwiflowEngine;
}
public void registrarDecisao(String externalTaskId, String decisao, IdentityContext identidade) {
kikwiflowEngine.completeExternalTask(externalTaskId,
Map.of("decisao", new ProcessVariable("decisao", decisao)),
identidade);
}
}
completeExternalTask mescla as variáveis na instância e continua o fluxo de forma síncrona, dentro da
mesma chamada, até a próxima espera ou o fim do processo. Para descobrir o externalTaskId de uma
instância, consulte as tarefas pendentes via ExternalTaskQueryService ou
GET /external-tasks. De fora da aplicação, o mesmo ciclo
(claim/unclaim/complete) está na API REST de tarefas externas.
Quando usar / quando não usar
Use EXTERNAL_TASK quando o próximo passo depende de um evento que chega em um momento
indeterminado — minutos, horas ou dias depois — e não faz sentido bloquear uma thread esperando por
ele: uma aprovação humana, um webhook de um parceiro, o upload de um
documento. Combine com um timer de borda quando essa espera precisa de um
prazo (ex.: recusar automaticamente se o analista não decidir em 48h).
Não use para lógica síncrona que roda inteiramente dentro da sua aplicação e retorna na hora —
isso é EXECUTABLE_TASK.
Próximo passo
Uma espera indefinida raramente é aceitável em produção — Timers e Prazos mostra como dar um prazo a uma tarefa externa. Se a espera é por um evento identificado por uma chave (um webhook com o número do pedido), e não por uma pessoa, veja Event Catcher e Event Thrower.