Runtime e observabilidade com Aspire
Depois que o Lino gera serviços, web apps e recursos de infraestrutura, o Aspire ajuda a executar tudo localmente com visibilidade. Observabilidade não é luxo: ela mostra se APIs, bancos, cache, mensageria e workers estão saudáveis.
Em aplicações com eventos, Outbox, workers, Redis, RabbitMQ e múltiplos módulos, muitos problemas não aparecem apenas na tela. Eles aparecem em logs, filas, jobs, migrations, parâmetros e recursos de runtime. Esta seção mostra como olhar para a solução como um sistema em execução, não apenas como arquivos gerados.
Execução com Aspire
O AppHost concentra a execução local da solução. Ele inicia serviços, aplicações web e dependências como PostgreSQL, Redis, RabbitMQ e workers.
dotnet run --project src/Aspire/AppHost/<ProjectName>.AppHost.csproj
Use o dashboard para verificar logs, variáveis, endpoints e estado dos recursos. Se um serviço falhar ao iniciar, comece pelo AppHost e pelas dependências que ele injeta.
O Aspire torna visível a topologia local: APIs, web apps, bancos, cache, broker de mensagens e workers aparecem como recursos relacionados. Essa visão ajuda a encontrar falhas de configuração que ficariam escondidas em uma execução manual, como connection string errada, parâmetro ausente, serviço sem endpoint ou dependência que ainda não subiu.
- Logs: acompanhe erros de inicialização, falhas de autenticação, problemas de migrations e mensagens de workers.
- Endpoints: confirme portas, URLs, health checks e links para web apps e APIs.
- Parâmetros: valide secrets e variáveis propagadas para cada serviço.
- Dependências: verifique se Redis, RabbitMQ e banco foram provisionados antes de diagnosticar a aplicação.
Recursos de banco de dados
Serviços gerados pelo Lino normalmente têm DbContexts, migrations e connection strings próprias. Em sistemas modulares, valide se cada módulo usa o banco/schema esperado e se migrations foram aplicadas no lugar correto.
- Confirme connection strings por ambiente.
- Execute migrations antes de testar fluxos dependentes de schema novo.
- Monitore falhas de conexão e tempo de query.
- Evite usar banco de produção em execução local.
Em um serviço simples, o banco acompanha o serviço. Em um serviço modular, o banco pertence ao serviço, mas cada módulo pode ter seu próprio schema, DbContext, migrations e scripts. Essa separação precisa aparecer também na operação: ao aplicar migrations, confirme serviço, módulo, provider e ambiente antes de executar.
Falhas de banco costumam aparecer como erro de API, mas a causa pode estar no AppHost, na connection string, em migration pendente, em schema inexistente ou em credencial local. Por isso, o diagnóstico deve começar pela cadeia completa: parâmetro no Aspire, recurso de banco ativo, migration aplicada, DbContext correto e endpoint chamando o módulo esperado.
Redis e cache
Redis pode ser usado para cache, estado temporário, tokens, rate limiting ou outros recursos dependendo dos templates habilitados. Cache melhora performance, mas introduz invalidação e consistência eventual.
Documente chaves, tempo de expiração e origem dos dados. Nunca armazene segredo sensível em cache sem entender criptografia, expiração e acesso.
Quando o projeto usa cache distribuído, múltiplas instâncias podem compartilhar valores, o que é útil para escala horizontal. Quando trabalha apenas com cache local em memória, cada processo mantém sua própria cópia. Essa diferença afeta comportamento em produção, testes de carga e invalidação de dados.
| Pergunta | Por que importa |
|---|---|
| Qual é a origem do dado em cache? | Define como recalcular o valor quando expira ou é invalidado. |
| Qual TTL é aceitável? | Determina por quanto tempo o sistema tolera dado potencialmente antigo. |
| O cache é por tenant, usuário ou global? | Evita vazamento de dados entre contextos e chaves mal modeladas. |
RabbitMQ e mensageria
Mensageria sustenta eventos de integração e comunicação assíncrona. Com Outbox, a aplicação não depende de publicar a mensagem no mesmo instante da transação; o worker pode tentar novamente.
- Verifique exchanges, filas e bindings gerados.
- Monitore mensagens paradas e consumidores inativos.
- Projete handlers idempotentes.
- Use logs de correlação para seguir o caminho da mensagem.
Eventos de integração são úteis exatamente porque o produtor não precisa esperar todos os consumidores. Mas isso desloca parte da complexidade para a operação: mensagens podem atrasar, consumidores podem falhar, payloads podem mudar e handlers podem ser executados mais de uma vez. A documentação do fluxo deve deixar claro qual evento é publicado, quem consome e qual estado local é atualizado.
Shadow Entities dependem dessa observabilidade. Se uma entidade de tenant ou usuário é replicada para outros módulos por evento, uma falha no consumidor pode deixar a cópia local desatualizada. O sistema precisa permitir diagnosticar o evento, a mensagem, o handler e a atualização realizada no banco do módulo consumidor.
Hangfire Dashboard
Quando background jobs estão habilitados, o Hangfire Dashboard ajuda a inspecionar jobs recorrentes, falhas, retries e execução de processamento de Outbox.
Proteja o dashboard em ambientes compartilhados. Ele expõe informações operacionais relevantes e não deve ficar público sem autenticação e autorização.
Use o dashboard como ferramenta de diagnóstico, não como substituto de logs e métricas. Ele mostra filas, tentativas e histórico de execução, mas a investigação completa ainda precisa de correlation id, logs estruturados e contexto de negócio para entender por que um job falhou.
- Retries: verifique se a falha é transitória ou se o job continuará falhando indefinidamente.
- Jobs recorrentes: confirme intervalo, lote e duração média de execução.
- Outbox: observe mensagens paradas, reprocessamento e handlers com exceção.
- Segurança: restrinja acesso, porque payloads e erros podem revelar dados sensíveis.
Workers e processamento em segundo plano
Workers executam tarefas que não devem bloquear requisições HTTP: envio de mensagens, processamento de Outbox, limpeza, sincronização e integrações externas.
- Use lotes adequados ao volume.
- Defina retries e tratamento de falhas.
- Registre erro com contexto suficiente para reprocessar.
- Não esconda falhas permanentes em logs genéricos.
Ao adicionar worker, defina também frequência, tamanho de lote, comportamento sob falha e impacto no domínio. Um worker que lê 100 registros a cada poucos segundos tem comportamento operacional diferente de um job diário; ambos precisam ser observados e dimensionados conforme volume real.
Não execute em background aquilo que precisa responder imediatamente ao usuário. Use worker para tarefas posteriores, integrações, notificações, reprocessamento e manutenção. Se o caso de uso depende do resultado para completar a transação, trate como fluxo síncrono ou modele um estado intermediário visível para o usuário.
