Integrações internas e externas
Integrações conectam a aplicação gerada pelo Lino a outros módulos, serviços internos e sistemas de terceiros. A escolha entre chamada síncrona, integração in-process, HTTP e eventos deve considerar acoplamento, latência, confiabilidade e propriedade dos dados.
O objetivo não é apenas chamar outro sistema. É declarar uma fronteira: quem fornece o dado, quem consome, qual contrato é público, o que acontece em caso de falha e se a operação precisa ser imediata ou pode ser processada depois.
Criando integrações
Integrações representam comunicação explícita com outro contexto, serviço interno ou sistema externo. Elas devem ter nome, contrato, autenticação, timeout, estratégia de erro e responsabilidade clara.
lino integration new --name <ServiceName> lino integration list
Use integration list para conferir integrações existentes antes de criar outra. Evite integrações genéricas, como CommonIntegration, porque elas tendem a acumular responsabilidades sem limite claro.
Antes de criar uma integração, defina qual problema ela resolve: consultar um cadastro externo, enviar uma cobrança, validar assinatura, sincronizar usuário, consumir um módulo interno ou publicar dados para outro sistema. Se a integração não possui intenção específica, ela provavelmente ainda não está pronta para virar contrato gerado.
- Nomeie pelo contexto integrado: prefira
Billing,Identity,CatalogouShippinga nomes genéricos. - Separe contrato de implementação: o domínio e a aplicação não devem depender diretamente de detalhes de transporte.
- Assuma falhas externas: toda integração remota pode ficar lenta, indisponível, retornar erro parcial ou mudar contrato.
Resources de integração
Resources representam objetos expostos ou consumidos por uma integração, como customers, invoices, tenants, subscriptions, users ou documents.
lino integration resource new --service <ServiceName> --module <ModuleName> --entity <EntityName> lino integration resource list --service <ServiceName> --module <ModuleName> --entity <EntityName>
Um resource de integração não precisa ser igual à entidade de domínio. Muitas vezes ele é um contrato de troca de dados, uma visão externa ou uma representação mínima necessária para comunicação entre contextos. Copiar a entidade inteira para o contrato externo costuma vazar detalhes internos e aumentar o custo de evolução.
- Modele o resource com o vocabulário do sistema integrado.
- Não vaze entidades internas como contrato externo.
- Defina quais campos são identificadores, filtros e dados retornados.
- Documente paginação, autenticação e limites de chamada quando existirem.
Quando o resource representa dados de outro módulo, inclua apenas o necessário para o consumidor. Esse mesmo princípio aparece nas shadow entities: o módulo consumidor mantém uma cópia local pequena, alinhada ao seu próprio caso de uso, em vez de depender do modelo completo do módulo produtor.
Operações de integração
Operações descrevem ações disponíveis em um resource de integração: criar, consultar, atualizar, cancelar, enviar, sincronizar ou validar.
lino integration operation new --service <ServiceName> --module <ModuleName> --entity <EntityName> lino integration operation list --service <ServiceName> --module <ModuleName> --entity <EntityName>
Cada operação deve definir intenção, entrada, saída, método de chamada, comportamento de erro e se pode ser reexecutada com segurança.
- Consultas devem ter timeout e tratamento para indisponibilidade.
- Comandos remotos devem ser idempotentes quando possível.
- Falhas externas não devem quebrar a transação principal se o negócio aceitar processamento assíncrono.
- Use logs e correlation id para rastrear chamadas entre sistemas.
Idempotência é especialmente importante em operações de escrita. Se uma tentativa falha depois que o sistema externo executou a ação, uma nova tentativa pode duplicar cobrança, criar registro repetido ou enviar mensagem duas vezes. Sempre que possível, use chaves de idempotência, identificadores externos ou regras de reexecução documentadas.
Consumindo integrações
Depois de modelar integração, resource e operação, use o consumo para conectar a aplicação ao contrato gerado. O objetivo é fazer o caso de uso depender de uma abstração nomeada, com entrada e saída previsíveis, em vez de espalhar chamadas HTTP, montagem de URL, headers, parsing de resposta e tratamento de erro por vários handlers.
lino integration consume
Casos de uso devem depender de abstrações, não de detalhes de HTTP espalhados pelo código. Isso facilita testes, troca de implementação e tratamento uniforme de falhas. Também evita que cada endpoint da aplicação reinvente timeout, autenticação, correlation id, serialização e mapeamento de erro de forma diferente.
- Valide dados antes de chamar serviço externo.
- Use cancellation token e timeout.
- Mapeie respostas externas para erros internos previsíveis.
- Não salve payload externo bruto como regra de domínio sem transformação.
HTTP vs. in-process
Integração in-process é simples e rápida quando os módulos rodam juntos. HTTP cria um contrato mais explícito entre processos, mas adiciona latência, falhas de rede e necessidade de resiliência.
A integração in-process não deve significar acesso livre a tudo. Mesmo dentro do mesmo runtime, o consumidor deve falar por contrato, não por entidade interna, DbContext ou repositório de outro módulo. O custo de rede é menor, mas o risco de acoplamento continua existindo.
| Cenário | Escolha comum | Observação |
|---|---|---|
| Módulos no mesmo monólito modular | In-process ou contrato interno | Preserve o limite; evite compartilhar entidade e persistência. |
| Serviço separado com deploy próprio | HTTP ou mensageria | Trate rede, autenticação, versionamento e indisponibilidade. |
| Processo assíncrono e tolerante a atraso | Evento de integração | Projete consumidores idempotentes e rastreáveis. |
HTTP é mais adequado quando o produtor e o consumidor têm runtimes separados ou quando você quer tornar a fronteira operacionalmente explícita. In-process é adequado quando a mesma aplicação hospeda os contextos e a resposta precisa ser imediata, desde que a dependência continue declarada por contrato.
Eventos vs. integrações síncronas
Use integração síncrona quando a resposta é necessária para concluir a operação atual. Use evento quando o consumidor pode reagir depois e a consistência eventual é aceitável.
Essa escolha é uma decisão de negócio antes de ser uma decisão técnica. Se um pedido só pode ser criado depois que o serviço de pagamento confirma autorização, a chamada síncrona pode ser parte essencial do caso de uso. Se a criação do pedido apenas precisa disparar notificação, atualização de projeção ou sincronização para outro módulo, um evento tende a ser mais apropriado.
| Necessidade | Abordagem | Cuidado técnico |
|---|---|---|
| Resposta imediata obrigatória | Integração síncrona | Timeout, fallback, erro previsível e contrato estável. |
| Efeito posterior tolerante a atraso | Evento de integração | Outbox, idempotência, retries e logs de correlação. |
| Leitura frequente de poucos dados externos | Shadow Entity ou projeção local | Sincronização, atualização eventual e modelo mínimo. |
