Pular para o conteúdo principal

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.

Pense em uma ficha de matrícula escolar

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​

  1. Criada — quando o fluxo alcança o nó, uma ExternalTask pendente é registrada.
  2. claim (opcional) — um worker ou operador reivindica a tarefa para si, evitando que outra pessoa processe o mesmo item ao mesmo tempo.
  3. 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 de commitBefore ou 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.