Pular para o conteúdo principal

Decisões e Gateways

Um EXCLUSIVE_GATEWAY roteia o fluxo para exatamente um ramo de saída, com base em uma decisão. A decisão em si nunca é uma expressão embutida em string — é sempre o retorno de um método Java, ou o valor de uma variável de processo já calculada.

Pense na triagem de um pronto-socorro

A mesma entrada leva a caminhos completamente diferentes dependendo de uma avaliação objetiva: casos graves seguem para um caminho, casos leves para outro. A avaliação acontece uma vez, no momento em que o paciente chega, com base em critérios definidos. A analogia para de funcionar se você esperar que a triagem reavalie o paciente continuamente — um gateway do Kikwiflow decide uma única vez, no instante em que o fluxo passa por ali, e não reconsidera a decisão depois.

"E se o score for baixo — quero mandar para uma mesa de análise?"

O processo de abertura de conta até aqui manda toda solicitação direto para o mesmo analista. Um gateway resolve isso: logo depois de Calcular Score, uma decisão de negócio separa quem segue para a aprovação comum de quem precisa passar por uma mesa de análise mais rígida antes.

O contrato AnswerProvider

@FunctionalInterface
public interface AnswerProvider {
/**
* Avalia o contexto atual e retorna uma String representando a hipótese de resposta.
* Retornar nulo é permitido, mas deve ser tratado explicitamente no modelo do processo.
*/
String resolve(EvaluationContext context);
}

As duas estratégias de providerType

Um EXCLUSIVE_GATEWAY resolve sua decisão de uma entre duas formas, declaradas via providerType:

providerTypeOrigem da decisãoCampo relevante
BEANBean Spring implementando AnswerProviderproviderBean
VARIABLEUma variável de processo já calculada por um nó anteriorproviderVariable

providerType: BEAN — a faixa de risco

A decisão depende de uma regra de negócio (a faixa em que o score cai), então é código Java:

package com.empresa.processo.decision;

import io.kikwiflow.execution.api.context.EvaluationContext;
import io.kikwiflow.execution.api.provider.AnswerProvider;
import org.springframework.stereotype.Component;

@Component("faixaRiscoAnswerProvider")
public class FaixaRiscoAnswerProvider implements AnswerProvider {

@Override
public String resolve(EvaluationContext context) {
int score = (int) context.getVariableValue("score").orElseThrow();
return score < 700 ? "ALTO" : null; // null segue para a aresta default
}
}
{
"id": "GATEWAY-FAIXA-RISCO",
"name": "Qual a faixa de risco?",
"type": "EXCLUSIVE_GATEWAY",
"providerType": "BEAN",
"providerBean": "faixaRiscoAnswerProvider",
"outgoing": [
{ "id": "flow-comum", "targetNodeId": "EXTERNAL_E5F3809A", "isDefault": true },
{ "id": "flow-mesa", "targetNodeId": "ANALISE_MESA", "expectedAnswer": "ALTO" }
]
}

Score de risco alto (< 700) segue para Análise de Mesa; qualquer outro caso cai na aresta isDefault e vai direto para Aprovar Abertura.

providerType: VARIABLE — o resultado da mesa

Quando a resposta já foi calculada por um nó anterior — por exemplo, um analista sênior que digitou a decisão ao completar a tarefa externa Análise de Mesa — o gateway só precisa lê-la como variável:

{
"id": "GATEWAY-RESULTADO-MESA",
"type": "EXCLUSIVE_GATEWAY",
"providerType": "VARIABLE",
"providerVariable": "resultadoMesa",
"outgoing": [
{ "id": "flow-mesa-aprova", "targetNodeId": "EXTERNAL_E5F3809A", "expectedAnswer": "APROVADA" },
{ "id": "flow-mesa-recusa", "targetNodeId": "END_RECUSADA", "isDefault": true }
]
}

Como a aresta de saída é escolhida

Dada a resposta resolvida (por BEAN ou VARIABLE), o motor escolhe a primeira aresta cujo expectedAnswer seja igual (comparação exata de string); se a resposta for null, escolhe a aresta com handlesNull: true; se nenhuma casar, escolhe a aresta isDefault: true, se existir.

Sempre declare uma aresta isDefault

Sem uma aresta isDefault, uma resposta inesperada (que não bate com nenhum expectedAnswer nem é null) não tem para onde ir. Declare isDefault: true sempre que o AnswerProvider puder evoluir com novos valores de resposta com o tempo, e handlesNull: true sempre que ele puder legitimamente retornar null. No exemplo da faixa de risco, FaixaRiscoAnswerProvider retorna null para "risco normal" de propósito — é o caso comum, e o caminho comum deve ser o default, não um expectedAnswer explícito.

Modelar no Craft

Arraste um Decision (Exclusive Gateway) logo depois de Calcular Score e ligue-o a dois caminhos. Ao conectar a saída de um Decision, a conexão nasce exigindo configuração de rota — marque uma como rota padrão (default) e dê à outra o valor esperado (ALTO). Preencha o campo do provider com faixaRiscoAnswerProvider. O nó Análise de Mesa é um External Task como qualquer outro (ver Tarefas Externas).

Implementar

O FaixaRiscoAnswerProvider acima é o único bean novo — um @Component nomeado, resolvido por nome igual ao providerBean do JSON, exatamente como um TaskHandler. O gateway providerType: VARIABLE não precisa de bean nenhum: ele lê uma variável que a tarefa externa anterior já gravou.

Operar no Monitor

Inicie duas instâncias pelo Monitor: uma com rendaDeclarada alta (score acima de 700) e outra com renda baixa. No canvas ao vivo, a primeira segue direto para Aprovar Abertura; a segunda acende o caminho de Análise de Mesa. Clicar no nó do gateway no diagrama filtra a dock de instâncias para as que passaram por ali — dá para ver, em tempo real, quantas foram para cada lado.

Quando usar / quando não usar

Use um EXCLUSIVE_GATEWAY quando o fluxo precisa escolher um entre vários caminhos com base em uma condição avaliada uma vez.

Não use quando:

  • Você quer executar vários passos ao mesmo tempo (não escolher um) — isso é Processamento Paralelo.
  • A decisão depende de esperar alguém — modele a espera como EXTERNAL_TASK e leia o resultado num gateway providerType: VARIABLE depois, como no exemplo do resultado da mesa acima.

Próximo passo

Gateways decidem para onde o fluxo vai. Para decidir quando algo acontece — prazos, expiração, o que fazer se o analista não decidir em 48h — veja Timers e Prazos.