Pular para o conteúdo principal
Página não listada
Esta página não está listada. Mecanismos de busca não irão indexá-la, e somente usuários que possuam o link direto poderão acessá-la

Guia de Integração: APIs do Kikwiflow para o Monitor de Instâncias

Este guia explica, endpoint por endpoint, como montar as três telas típicas de um monitor de instâncias (visão geral por processo, detalhe de um processo, detalhe de uma instância) usando as APIs REST de kikwi-management-rest já descritas nas páginas anteriores desta seção. É o complemento prático do guia de busca avançada (que aprofunda só o /search).

Todas as chamadas abaixo pressupõem kikwi-management-rest com um QueryRepository no contexto (é o padrão quando kikwi-runtime-persistence-mongodb-spring-boot-autoconfigure está no classpath — ver Visão Geral). Ajuste o prefixo de path para o kikwiflow.rest.base-path configurado na sua aplicação (default /kikwiflow/api/v1).


1. Tela "Visão geral": processo × quantidade de instâncias × incidentes

Objetivo: uma lista de processos, cada um com "quantas instâncias" e "quantos incidentes".

Passo 1 — listar as definições de processo

GET /process-definitions

Devolve todas as versões de todas as definições, ordenadas por version decrescente — não é uma lista deduplicada por processo. Para montar "um card por processo", agrupe por key no cliente e fique só com a primeira ocorrência de cada uma (já vem em primeiro por causa da ordenação):

const allVersions = await fetch('/process-definitions').then(r => r.json());
const latestByKey = new Map();
for (const def of allVersions) {
if (!latestByKey.has(def.key)) latestByKey.set(def.key, def); // 1ª ocorrência = versão mais alta
}

Alternativa, se você já sabe as keys que quer mostrar: GET /process-definitions/one-by-key/{key}, uma chamada por chave, sempre a versão mais recente — sem precisar deduplicar nada.

Passo 2 — métricas macro por processo

Para cada definição (id) obtida no passo 1:

GET /pulse/process-definition/{processDefinitionId}/snapshot

Resposta (KKFProcessStats, campos relevantes para esta tela):

{
"id": "fc451f6f-a944-4dbb-b2ba-b5fb6433f40a",
"key": "intermediacao-veiculos",
"name": "Intermediação de Veículos",
"metrics": { "running": 42, "sla": 100.0, "fail": 3 }
}
  • metrics.running → instâncias com status: ACTIVE agora (não é o total histórico).
  • metrics.fail → incidentes com status: OPEN agora, para esse processo.
  • metrics.sla → hoje é sempre 100.0, hardcoded (StatsService/getProcessMacroMetrics não calcula SLA real ainda) — não use esse campo para nada além de exibir um placeholder.

Se o que você quer é o total histórico de instâncias (todas, não só as ativas — inclui COMPLETED e CANCELLED), use em vez disso:

GET /process-instances/count?process-definition-id={processDefinitionId}
→ { "total": 1284 }

Não existe hoje um endpoint que devolva as duas métricas (running + fail) para todos os processos numa única chamada — é uma requisição por processo (N+1), aceitável para a cardinalidade típica de definições de processo (dezenas, não milhares). Se isso virar gargalo, é o item 16 do documento de observabilidade (GET/POST /process-instances/count genérico) mais um "macro metrics em lote" — nenhum dos dois existe ainda.

Alternativa em tempo real (sem polling manual)

Troque o passo 2 por SSE, uma conexão por processo que você está exibindo na tela:

GET /pulse/process-definition/{processDefinitionId}/snapshot/stream

Reenvia o mesmo KKFProcessStats a cada kikwiflow.pulse.sse-endpoints.interval (default 5000ms) enquanto a conexão estiver aberta — troque polling manual por só manter a conexão viva e atualizar a UI a cada evento.


2. Tela "Detalhe do processo": atividade × quantidade de instâncias × incidentes

Objetivo: o mesmo processo de antes, agora granular por atividade/nó do diagrama.

Mesma chamada do passo 2 acima:

GET /pulse/process-definition/{processDefinitionId}/snapshot

desta vez lendo flowNodes — um mapa nodeId → definição do nó (com métricas embutidas):

{
"flowNodes": {
"AGUARDANDO_CONTATO": {
"type": "EXTERNAL_TASK",
"id": "AGUARDANDO_CONTATO",
"name": "Aguardando contato do vendedor",
"metrics": { "running": 18, "sla": 100.0, "fail": 2 }
},
"AGUARDA_PAGAMENTO": {
"type": "EVENT_CATCHER",
"id": "AGUARDA_PAGAMENTO",
"catchType": "GROUP",
"matchPolicy": "ALL",
"metrics": { "running": 5, "sla": 100.0, "fail": 0 }
},
"GATEWAY_APROVACAO": {
"type": "EXCLUSIVE_GATEWAY",
"id": "GATEWAY_APROVACAO",
"metrics": null
}
}
}

Pontos de atenção:

  • metrics é preenchido para EXECUTABLE_TASK, EXTERNAL_TASK, EVENT_CATCHER, CALL_ACTIVITY_COORDINATOR e TIMER_TASK — os cinco tipos de nó que são materializados como ExecutableTask/ExternalTask e onde "quantas instâncias estão paradas aqui" faz sentido como conceito (StatsService.buildProcessSnapshot). Os dois últimos só passaram a receber metrics a partir desta revisão — antes, CALL_ACTIVITY_COORDINATOR aparecia sempre com metrics: null mesmo quando havia dados reais (a tarefa coordenadora já é uma ExecutableTask normal na agregação getMetricsByNodeForProcessDefinition; só não estava sendo repassada). Gateways e boundary events continuam sempre com metrics: null — não é bug, é intencional; não há "fila" nesses tipos de nó da mesma forma.
  • flowNodes[nodeId].metrics.running conta ExecutableTask/ExternalTask ativas naquele taskDefinitionId — é o "quantas instâncias estão paradas nesta atividade agora". fail conta as que estão com status de erro (ExecutableTaskStatus.ERROR).
  • O type de cada entrada de flowNodes é o discriminador polimórfico (KKFFlowNodeDefinition) — use-o para saber que campos extras esperar (KKFExternalTaskDefinition, KKFEventCatcherDefinition, KKFCallActivityDefinition, etc., um por tipo de nó).
  • Todos os 15 tipos de nó do modelo têm representação aqui, incluindo EVENT_CATCHER e CALL_ACTIVITY_COORDINATOR (KKFCallActivityDefinition inclui iterationMode: SEQUENTIAL/PARALLEL) — ver §4 para o porquê disso ser uma garantia nova.
  • Mesma variante SSE do passo 2 acima serve aqui (.../snapshot/stream) — é a mesma resposta, só que reenviada periodicamente; um único stream alimenta as telas 1 e 2 ao mesmo tempo se você já tiver os dados carregados.

3. Tela "Detalhe da instância": onde ela está parada

Objetivo: dado um processInstanceId, mostrar em qual(is) nó(s) ela está parada e, quando esse nó for um EVENT_CATCHER em grupo ou um CALL_ACTIVITY_COORDINATOR (subprocesso), mostrar o progresso — não só "está parado", mas "3 de 5 eventos recebidos" ou "2 de 3 subprocessos concluídos".

Passo 1 — snapshot completo da instância

GET /process-instances/{id}/snapshot

Resposta (ProcessInstanceSnapshot):

{
"instance": {
"id": "ae8fd836-...",
"businessKey": "100234",
"status": "ACTIVE",
"processDefinitionId": "fc451f6f-...",
"activeNodes": { "AGUARDA_PAGAMENTO": 1 },
"parentInstanceId": null,
"callerTaskId": null,
"callerBranchId": null
},
"executableTasks": [ ... ],
"externalTasks": [ ... ],
"incidents": [ ... ],
"eventCatcherWaitStatus": [
{
"taskDefinitionId": "AGUARDA_PAGAMENTO",
"externalTaskId": "parent-task-id",
"matchPolicy": "ALL",
"totalCorrelationKeys": 5,
"receivedCount": 3,
"pendingCorrelationKeys": ["pedido-104", "pedido-105"]
}
]
}

instance.activeNodes (Map<nodeId, count>) é o ponto de partida: diz em quais nós a instância está parada agora, e quantos "tokens" ativos há em cada um (relevante para PARALLEL_GATEWAY/loops). Cruze cada nodeId com o diagrama (flowNodes da tela 2) para saber o tipo do nó e decidir o que mostrar:

Tipo do nó paradoO que mostrarOnde vem o dado
EXECUTABLE_TASK / EXTERNAL_TASKnome da tarefa, assignee (ExternalTask.assignee), há quanto tempo está parada (createdAt), se está em retry/erro (ExecutableTask.status/error/retries)filtre executableTasks/externalTasks do snapshot por taskDefinitionId == nodeId
EVENT_CATCHER (GROUP)"N de M eventos recebidos", quais chaves faltameventCatcherWaitStatusnovo campo, ver §3.1
CALL_ACTIVITY_COORDINATOR (subprocesso)quantos filhos, quantos concluíram, status de cada umPOST /process-instances/search com parentInstanceIdnovo filtro, ver §3.2
BOUNDARY_* (timer/catch event/error handler)geralmente não aparece em activeNodes isoladamente — é metadado anexado ao nó pai; sua existência aparece como boundaryEvents dentro da ExecutableTask/ExternalTask do nó paimesmo lugar da linha do EXECUTABLE_TASK/EXTERNAL_TASK pai

3.1 Progresso de um EVENT_CATCHER em grupo — eventCatcherWaitStatus (novo)

Antes, para saber "quantos eventos já chegaram" você precisaria filtrar externalTasks manualmente por type: EVENT_CATCHER_PARENT/EVENT_CATCHER_CHILD e cruzar coordinatorTaskId/status na mão. Agora o snapshot já entrega isso computado em eventCatcherWaitStatus, um item por EVENT_CATCHER ativo na instância (GROUP ou STANDALONE):

CampoSignificado
taskDefinitionIdid do nó EVENT_CATCHER na definição — cruza com flowNodes da tela 2
externalTaskIdid da tarefa coordenadora (GROUP) ou da própria tarefa (STANDALONE)
matchPolicyALL (só conclui com todas as chaves), ANY (primeira chave vence), ou null para STANDALONE
totalCorrelationKeysquantas chaves esse nó espera ao todo
receivedCountquantas já chegaram
pendingCorrelationKeysquais ainda faltam — útil para debug ("por que esse pedido não anda? falta o webhook de pedido-105")

Renderização sugerida: "${receivedCount} de ${totalCorrelationKeys} eventos recebidos" + lista de pendingCorrelationKeys como itens pendentes. Um EVENT_CATCHER STANDALONE sempre aparece com totalCorrelationKeys: 1, receivedCount: 0 — ele só existe na lista enquanto está esperando; quando a chave chega, a tarefa é removida (não fica um registro com receivedCount: 1).

Detalhe de correção para matchPolicy: ANY: receivedCount é calculado contando as tarefas-filha com status CORRELATED (não o tamanho de uma lista de "pendentes" da tarefa-mãe) — isso importa porque em ANY a primeira resposta já conclui o nó inteiro (não há "recebimento parcial"), então você não vai ver receivedCount subir gradualmente num ANY como sobe num ALL; ele pula de 0 direto para o nó desaparecer de activeNodes (a instância avançou).

3.2 Subprocessos: filhos e seus status — filtro parentInstanceId (novo)

Quando o nó parado é um CALL_ACTIVITY_COORDINATOR, o snapshot da instância pai não traz o status dos filhos embutido (cada filho é uma ProcessInstance própria, com seu próprio ciclo de vida). Para listá-los:

POST /process-instances/search
{ "parentInstanceId": "ae8fd836-c6a8-4dd1-af8d-0e6ec3530657", "size": 100 }
{
"content": [
{ "id": "child-1", "businessKey": "100234#0", "status": "COMPLETED", "parentInstanceId": "ae8fd836-...", "callerTaskId": "coord-task-id", "callerBranchId": "coord-task-id:0" },
{ "id": "child-2", "businessKey": "100234#1", "status": "ACTIVE", "activeNodes": { "AGUARDA_ATIVACAO": 1 }, "parentInstanceId": "ae8fd836-...", "callerTaskId": "coord-task-id", "callerBranchId": "coord-task-id:1" }
],
"totalElements": 2
}

Monte "2 de 3 subprocessos concluídos" contando status: COMPLETED sobre totalElements (ou sobre content.length se totalElements ainda não bateu, ex.: enquanto a coleção de filhos ainda está sendo populada por um fan-out SEQUENTIAL). Para o filho ainda ativo, activeNodes do próprio item já diz onde ele está parado — a mesma lógica desta seção 3 se aplica recursivamente (um filho pode, por sua vez, ser pai de outro subprocesso).

Por que via /search e não um campo embutido no snapshot do pai: o número de filhos de um CALL_ACTIVITY_COORDINATOR pode ser grande (é dirigido por uma collectionVariable do processo) e cada filho tem seu próprio ciclo de vida independente — embuti-los cruaria no snapshot do pai duplicaria dados que o /search já serve, paginado, com todos os filtros existentes (status, tenant, etc.) de graça. Se quiser saber rapidamente "esta instância é filha de outra?" sem ir ao /search, os três campos já vêm na própria instância: ProcessInstanceSummary/ProcessInstance têm parentInstanceId/callerTaskId/callerBranchIdnull numa instância raiz, preenchidos numa filha.

3.3 Incidentes da instância

GET /process-instances/{id}/incidents

Lista de Incident (não paginada — normalmente poucos por instância). Combine com o passo 1: se activeNodes mostra a instância parada num nó mas o incidente aponta para esse mesmo taskDefinitionId, é sinal de que ela está parada por erro, não por espera normal — distinga os dois casos na UI (ex.: ícone de alerta vs. ícone de relógio).


4. O que mudou nesta rodada (contexto para quem já integrou antes)

Se seu monitor já consome essas APIs, os pontos novos que valem revisão:

  1. eventCatcherWaitStatus é um campo novo em ProcessInstanceSnapshot (GET /process-instances/{id}/snapshot) — aditivo, não quebra nada existente.
  2. parentInstanceId/callerTaskId/callerBranchId são campos novos em ProcessInstanceSummary — aparecem agora em POST /process-instances/search e GET /process-instances/summary, além de já existirem em ProcessInstance (GET /process-instances/{id}). Também aditivo.
  3. parentInstanceId é um filtro novo em POST /process-instances/search (§3.2 acima).
  4. iterationMode é um campo novo em KKFCallActivityDefinition (dentro de flowNodes na tela 2).
  5. Todos os 15 tipos de nó (incluindo EVENT_CATCHER e CALL_ACTIVITY_COORDINATOR) são garantidos por compilação a continuar aparecendo em flowNodes — antes, um tipo de nó novo no motor podia quebrar silenciosamente GET /pulse/process-definition/{id}/snapshot em runtime (já aconteceu antes); agora isso vira erro de build do lado do servidor, não um 500 em produção.
  6. size em /process-instances/search agora é limitado a 100 mesmo se você pedir mais — se seu monitor dependia de pedir páginas maiores, ajuste para paginar de verdade.
  7. orderBy em /process-instances/search agora só aceita id, businessKey, status, processDefinitionId, startedAt, endedAt — um valor fora dessa lista agora devolve 400 em vez de ser ignorado silenciosamente ou quebrar a ordenação no servidor.
  8. CALL_ACTIVITY_COORDINATOR e TIMER_TASK agora recebem metrics em flowNodes (tela 2) — se seu monitor já tinha uma regra tipo "se metrics for null, não desenha o número", ela vai começar a mostrar número de verdade para esses dois tipos a partir de agora (era sempre null antes, mesmo com dados reais).

Nada do que já funcionava foi removido ou renomeado — são só campos/filtros novos e validação mais estrita em dois parâmetros que já existiam.

5. Referência rápida

TelaEndpoint principalComplementos
1. Visão geralGET /process-definitions + GET /pulse/process-definition/{id}/snapshot (×N)GET /process-instances/count?process-definition-id= para total histórico
2. Detalhe do processoGET /pulse/process-definition/{id}/snapshot (campo flowNodes)versão SSE: .../snapshot/stream
3. Detalhe da instânciaGET /process-instances/{id}/snapshotPOST /process-instances/search com parentInstanceId para filhos; GET /process-instances/{id}/incidents