Integraciones internas y externas
Las integraciones conectan la aplicación generada por Lino con otros módulos, servicios internos y sistemas de terceros. La elección entre llamadas síncronas, integración in-process, HTTP y eventos debe considerar el acoplamiento, la latencia, la confiabilidad y la propiedad de los datos.
El objetivo no es solo llamar a otro sistema. Es declarar un límite: quién proporciona los datos, quién los consume, qué contrato es público, qué ocurre en caso de falla y si la operación debe ser inmediata o puede procesarse después.
Creando integraciones
Las integraciones representan una comunicación explícita con otro contexto, servicio interno o sistema externo. Deben tener nombre, contrato, autenticación, timeout, estrategia de error y una responsabilidad clara.
lino integration new --name <ServiceName> lino integration list
Use integration list para revisar las integraciones existentes antes de crear otra. Evite integraciones genéricas, como CommonIntegration, porque tienden a acumular responsabilidades sin un límite claro.
Antes de crear una integración, defina qué problema resuelve: consultar un registro externo, enviar un cobro, validar una suscripción, sincronizar un usuario, consumir un módulo interno o publicar datos en otro sistema. Si la integración no tiene una intención específica, probablemente aún no está lista para convertirse en un contrato generado.
- Nómbrela por el contexto integrado: prefiera
Billing,Identity,CatalogoShippingantes que nombres genéricos. - Separe contrato de implementación: el dominio y la aplicación no deben depender directamente de detalles de transporte.
- Asuma fallas externas: toda integración remota puede volverse lenta, no estar disponible, devolver un error parcial o cambiar su contrato.
Resources de integración
Los resources representan objetos expuestos o consumidos por una integración, como customers, invoices, tenants, subscriptions, users o documents.
lino integration resource new --service <ServiceName> --module <ModuleName> --entity <EntityName> lino integration resource list --service <ServiceName> --module <ModuleName> --entity <EntityName>
Un resource de integración no necesita ser igual a la entidad de dominio. Muchas veces es un contrato de intercambio de datos, una vista externa o una representación mínima necesaria para la comunicación entre contextos. Copiar la entidad completa al contrato externo suele filtrar detalles internos y aumentar el costo de evolución.
- Modele el resource con el vocabulario del sistema integrado.
- No exponga entidades internas como contrato externo.
- Defina qué campos son identificadores, filtros y datos devueltos.
- Documente paginación, autenticación y límites de llamada cuando existan.
Cuando el resource representa datos de otro módulo, incluya solo lo necesario para el consumidor. Este mismo principio aparece en las shadow entities: el módulo consumidor mantiene una pequeña copia local, alineada con su propio caso de uso, en lugar de depender del modelo completo del módulo productor.
Operaciones de integración
Las operaciones describen acciones disponibles en un resource de integración: crear, consultar, actualizar, cancelar, enviar, sincronizar o validar.
lino integration operation new --service <ServiceName> --module <ModuleName> --entity <EntityName> lino integration operation list --service <ServiceName> --module <ModuleName> --entity <EntityName>
Cada operación debe definir intención, entrada, salida, método de llamada, comportamiento de error y si puede reejecutarse de forma segura.
- Las consultas deben tener timeout y tratamiento para indisponibilidad.
- Los comandos remotos deben ser idempotentes cuando sea posible.
- Las fallas externas no deben romper la transacción principal si el negocio acepta procesamiento asíncrono.
- Use logs y correlation id para rastrear llamadas entre sistemas.
La idempotencia es especialmente importante en operaciones de escritura. Si un intento falla después de que el sistema externo ejecutó la acción, un nuevo intento puede duplicar un cobro, crear un registro repetido o enviar un mensaje dos veces. Siempre que sea posible, use claves de idempotencia, identificadores externos o reglas de reejecución documentadas.
Consumiendo integraciones
Después de modelar integración, resource y operación, use el consumo para conectar la aplicación al contrato generado. El objetivo es hacer que el caso de uso dependa de una abstracción nombrada, con entrada y salida previsibles, en lugar de dispersar llamadas HTTP, armado de URL, headers, parsing de respuesta y tratamiento de errores por varios handlers.
lino integration consume
Los Use Cases deben depender de abstracciones, no de detalles de HTTP dispersos por el código. Esto facilita las pruebas, el cambio de implementación y el tratamiento uniforme de fallas. También evita que cada endpoint de la aplicación reinvente timeout, autenticación, correlation id, serialización y mapeo de errores de forma diferente.
- Valide datos antes de llamar a un servicio externo.
- Use cancellation token y timeout.
- Mapee respuestas externas a errores internos previsibles.
- No guarde payload externo bruto como regla de dominio sin transformación.
HTTP vs. in-process
La integración in-process es simple y rápida cuando los módulos se ejecutan juntos. HTTP crea un contrato más explícito entre procesos, pero agrega latencia, fallas de red y necesidad de resiliencia.
La integración in-process no debe significar acceso libre a todo. Incluso dentro del mismo runtime, el consumidor debe comunicarse mediante contrato, no mediante una entidad interna, DbContext o repositorio de otro módulo. El costo de red es menor, pero el riesgo de acoplamiento sigue existiendo.
| Escenario | Elección común | Observación |
|---|---|---|
| Módulos en el mismo monolito modular | In-process o contrato interno | Preserve el límite; evite compartir entidad y persistencia. |
| Servicio separado con despliegue propio | HTTP o mensajería | Trate red, autenticación, versionado e indisponibilidad. |
| Proceso asíncrono y tolerante a retraso | Evento de integración | Diseñe consumidores idempotentes y rastreables. |
HTTP es más adecuado cuando productor y consumidor tienen runtimes separados o cuando se quiere hacer explícito el límite operacional. In-process es adecuado cuando la misma aplicación hospeda los contextos y la respuesta debe ser inmediata, siempre que la dependencia siga declarada por contrato.
Eventos vs. integraciones síncronas
Use integración síncrona cuando la respuesta sea necesaria para concluir la operación actual. Use un evento cuando el consumidor pueda reaccionar después y la consistencia eventual sea aceptable.
Esta elección es una decisión de negocio antes que una decisión técnica. Si un pedido solo puede crearse después de que el servicio de pago confirma la autorización, la llamada síncrona puede ser una parte esencial del caso de uso. Si la creación del pedido solo necesita disparar una notificación, actualización de proyección o sincronización hacia otro módulo, un evento tiende a ser más apropiado.
| Necesidad | Enfoque | Cuidado técnico |
|---|---|---|
| Respuesta inmediata obligatoria | Integración síncrona | Timeout, fallback, error previsible y contrato estable. |
| Efecto posterior tolerante a retraso | Evento de integración | Outbox, idempotencia, retries y logs de correlación. |
| Lectura frecuente de pocos datos externos | Shadow Entity o proyección local | Sincronización, actualización eventual y modelo mínimo. |
