Saltar a contenido

🦎 Netcomp, Webhooks y Leader/Follower — Estado Actual

Fecha: 1 de abril de 2026 Propósito: Tener claridad total sobre qué datos emite el webhook de la cola, qué diferencia hay entre eventos de Encounter vs Message, y cómo la migración Leader/Follower condiciona a Pet Flows Fuentes: Código fuente de dkv-pet-flows-admin (containers/Queue, services/netcomp), documentación en investigacion_dkv_pet_cloud.md


1. La Entidad Queue — Anatomía Completa de Notificaciones

Del análisis del código en QueueDetailsNotifications.jsx y Queue/index.jsx, la entidad Queue (Cola) tiene estos campos de notificación:

Campos de Notificación de la Cola

Campo Tipo Descripción
notify_new_encounter_doctors_enabled bool Notificar a doctores cuando entra un caso nuevo
notify_new_encounter_recipients_enabled bool Notificar a destinatarios externos cuando entra caso
notify_new_encounter_recipients string[] Lista de emails/destinatarios para caso nuevo
notify_max_unassigned_time_doctors_enabled bool Alertar a doctores si caso no asignado en tiempo
notify_max_unassigned_time_recipients_enabled bool Alertar a destinatarios si caso no asignado
notify_max_unassigned_time_recipients string[] Lista de destinatarios para alerta de asignación
notify_max_inactive_time_doctors_enabled bool Alertar a doctores por inactividad
notify_max_inactive_time_recipients_enabled bool Alertar a destinatarios por inactividad
notify_max_inactive_time_recipients string[] Lista de destinatarios para alerta de inactividad
webhook_new_message_recipients string[] URLs webhook para nuevos mensajes

Campos de Temporización (SLA)

Campo Tipo Descripción Valor ejemplo
max_unattended_time int (min) Tiempo máximo de respuesta del doctor 15 min
max_unassigned_time int (min) Tiempo máximo sin asignar doctor 30 min
max_inactive_time int (min) Tiempo máximo de inactividad 15 min
max_inactive_patient_warning_time int (min) Aviso de inactividad del paciente configurable
max_inactive_patient_time int (min) Cierre por inactividad del paciente configurable
unassign_unattended bool Desasignar doctor si supera respuesta true/false
revoke_inactive bool Revocar caso por inactividad + re-evaluar políticas true/false
close_inactive_encounters bool Cerrar casos inactivos automáticamente true/false
close_unassigned_inactive bool Cerrar no asignados inactivos true/false

2. Los 3 + 1 Sistemas de Eventos en una Cola

graph TD
    QUEUE["🏥 Cola (Queue)<br/>ej: Telemedicina"]

    subgraph "3 Notificaciones Internas"
        N1["📥 Entrada de Caso<br/>notify_new_encounter_*<br/>→ Email a destinatarios"]
        N2["⏰ Tiempo Asignación<br/>notify_max_unassigned_time_*<br/>→ Email + alerta doctor"]
        N3["😴 Inactividad<br/>notify_max_inactive_time_*<br/>→ Email + revoke"]
    end

    subgraph "1 Webhook Externo"
        WH["🔗 Webhook<br/>webhook_new_message_recipients<br/>→ HTTP POST a URLs externas"]
    end

    QUEUE --> N1 & N2 & N3 & WH

    style QUEUE fill:#009BE0,color:#fff
    style N1 fill:#059669,color:#fff
    style N2 fill:#D97706,color:#fff
    style N3 fill:#ef4444,color:#fff
    style WH fill:#7C3AED,color:#fff

[!IMPORTANT] Hallazgo clave: Las 3 notificaciones internas (N1, N2, N3) son emails a destinatarios humanos (operadores, jefes de cola). El webhook (WH) es un HTTP POST a URLs de máquinas (originalmente pensado para pools de terceros). Pet Flows se engancha al webhook.


3. Encounter vs Message — ¿Dos tipos de evento?

Del análisis de la API del admin:

Encounter (Caso)

POST /encounters/{id}/create_support    → Crear soporte
POST /encounters/{id}/token             → Obtener token
POST /encounters/{id}/doctor_close      → Cerrar caso con motivo
GET  /encounters/{id}/calls             → Llamadas del caso

Un Encounter es un caso médico completo: apertura, asignación a doctor, conversación, cierre. Es la entidad de nivel alto.

Message (Mensaje)

POST /messages                          → Crear mensaje
GET  /messages?from=0&size=999          → Listar mensajes
PUT  /messages/{id}                     → Actualizar mensaje
GET  /messages/types                    → Tipos de mensaje

Un Message tiene: message_id, brand_id, service_id, queue_id, speciality_id, descriptions, type, enabled.

Los mensajes son templates de mensajes predefinidos (respuestas enlatadas), NO mensajes individuales de chat. Son configurables por cola, marca y especialidad.

El Webhook — ¿Qué se envía? (VERIFICADO)

[!SUCCESS] Hemos verificado el código fuente tanto en netcomp (Erlang) como en pet-cloud (Java).

  1. El webhook se dispara EXCLUSIVAMENTE cuando se crea un nuevo mensaje en el chat (nkchat_message_event en Erlang, TelemedExtCallback.nkchatMessageEvent en Java).
  2. ESTO INCLUYE los mensajes del sistema (ej: "Tu consulta ha sido cerrada", creados por el ususario admin / system).
  3. El Payload es perfecto: Cada POST incluye la "foto" completa de la entidad:
    {
      "encounter": { ... todo el detalle de la consulta, tags, estado ... },
      "message": { "type": "created", "message_id": "...", "text": "...", "created_by_role": "patient|professional|system" }
    }
    

Flujo en Pet Flows: - Recibiremos webhooks por CADA interacción en el chat. - Al incluir el campo "encounter", no necesitamos hacer llamadas REST adicionales para saber el estado de la consulta, ¡viene de regalo en el evento! - Eventos de "creación" y "cierre" de la consulta se deducen a través de la recepción de los mensajes de sistema generados por el backend en esos mismos instantes.


4. Leader/Follower — Impacto en Pet Flows

Contexto

graph LR
    subgraph "Estado Actual"
        NC["🦎 netcomp (Erlang)<br/>LEADER actual<br/>ES 6 (persistencia)"]
        PC["🐾 pet-cloud (Java)<br/>FOLLOWER actual<br/>PG + ES 7"]
        RMQ["RabbitMQ<br/>Sync bidireccional"]
    end

    subgraph "Estado Futuro (GoLive Julio 2026)"
        PC2["🐾 pet-cloud<br/>LEADER<br/>PG + ES 7"]
        NC2["🦎 netcomp<br/>FOLLOWER<br/>Solo lectura"]
    end

    subgraph "Estado Final"
        PC3["🐾 pet-cloud<br/>SOLO SISTEMA<br/>netcomp eliminado"]
    end

    NC <-->|"AMQP payload completo"| RMQ
    PC <-->|"AMQP payload completo"| RMQ

    NC -->|"GoLive"| PC2
    PC -->|"GoLive"| NC2

    PC2 -->|"Migración completa"| PC3

    style NC fill:#ef4444,color:#fff
    style PC fill:#009BE0,color:#fff
    style NC2 fill:#f97316,color:#fff
    style PC2 fill:#009BE0,color:#fff
    style PC3 fill:#059669,color:#fff

Regla Crítica para Pet Flows

[!IMPORTANT] Solo el LEADER debe emitir webhooks a Pet Flows.

Si ambos sistemas emiten webhooks (netcomp como leader actual + pet-cloud como follower), Pet Flows recibiría eventos duplicados.

Solución: Configurar webhook_new_message_recipients solo en el sistema que sea Leader en cada momento: - Ahora: netcomp es Leader → netcomp emite el webhook - Post GoLive: pet-cloud es Leader → pet-cloud emite el webhook - Final: pet-cloud único sistema → webhook nativo

Implicación para la Arquitectura

Fase Leader Webhook emitido por Cambio necesario en Pet Flows
Pre-GoLive (ahora → julio) netcomp netcomp Ninguno — solo configurar URL
GoLive (julio) pet-cloud pet-cloud Verificar que el payload es compatible
Post-migración pet-cloud (solo) pet-cloud Ninguno

[!TIP] Buena noticia: Como ambos sistemas envían "fotos completas" del estado de la entidad via RabbitMQ, el payload del webhook debería ser idéntico independientemente de quién sea el Leader. Pero hay que verificar que pet-cloud implementa el mismo mecanismo de webhook que netcomp.


5. Preguntas Abiertas RESUELTAS (Spike Terminado)

# Pregunta Resultado del Spike
1 ¿El webhook se dispara por mensaje o por encounter? Por mensaje. Únicamente cuando se inserta un mensaje de chat, incluyendo mensajes automáticos del sistema.
2 ¿Qué campos incluye el payload del webhook? Híbrido ideal. Incluye un nodo "message" y un nodo "encounter" con la instantánea del caso en ese momento.
3 ¿Pet-cloud implementa el mismo mecanismo de webhook que netcomp? . Implementado en com.dkv.pet.module.dkvtelemed.TelemedExtCallback.java con idéntico payload cifrado.
4 ¿Hay un evento de tipo "encounter_closed" en el webhook? SE INFIERE. Cuando se cierra un caso en netcomp/pet-cloud, se auto-genera un mensaje para el paciente. Ese mensaje gatilla el webhook y trae consigo el "encounter": { "status": "closed" }.
5 ¿Durante Leader/Follower, ambos envían webhooks o solo el Leader? ⚠️ Punto de Riesgo Menor. En teoría, si ambos ecosistemas están suscritos vía RabbitMQ, podrían emitir webhooks duplicados. Mitigación Pet Flows: Debe procesar eventos basados en el message_id ignorando procesamientos repetidos (idempotencia en el broker Dapr Pub/Sub).

Documentos Relacionados

Documento Propósito
01 — Mapa de Piezas Vista general del ecosistema
aux_04 — DTM Distributed Task Manager
04 — Anatomía MVP Backlog Flujo concreto que depende de estos webhooks