Skip to main content

ADR-001 — Uso de ILogQueueService para logs de negócio em handlers de query

Data: 2026-05-14
Status: Aceito
Contexto: Task #193232 — Ajuste endpoint GET api/payment/v2/{id} (GetInfo) — Upsell no fluxo de vendas
Autor: Pesquisa gerada via análise de código (OpenCode)


Contexto

Durante o desenvolvimento da Task #193232, surgiu a necessidade de registrar um evento de negócio no GetInfoQueryHandler: quando os itens recomendados de um carrinho não são retornados por expiração da janela de 1 hora, o sistema deve notificar o AllLogs.

O GetInfoQueryHandler é um handler de query (somente leitura) e, até este momento, não utilizava ILogQueueService. A dúvida era: devemos usar logging convencional (ILogger) ou a fila AllLogs (ILogQueueService)?


Decisão

Usar ILogQueueService com LogQueueMessageEvent.SaveLogOrderHistoryMessage, injetando-o no construtor do GetInfoQueryHandler.

O padrão de chamada é:

_ = _logQueueService.EnqueueAsync(
LogQueueMessageEvent.SaveLogOrderHistoryMessage(
_userProvider.GetSchemaName(),
order.Id,
$"Itens recomendados não retornados para CartId {cart.Id}: janela de 1 hora expirada."));

Justificativa

Por que ILogQueueService e não ILogger?

CritérioILoggerILogQueueService (AllLogs)
Visibilidade para o negócioApenas infraestrutura/devVisível via sql para análise de vendas
Padrão adotado no checkoutNão usado para eventos de negócioPadrão consolidado em todos os handlers de payment
Rastreabilidade por paymentIdNãoSim — o log é indexado por paymentId
Usado em handlers de queryInéditoPrimeira vez, mas sem impedimento técnico

O AllLogs é o canal padrão para eventos de negócio rastreáveis por pedido na Checkout API. O uso de ILogger seria adequado apenas para diagnósticos técnicos de infraestrutura.

Por que é aceitável em um handler de query?

Handlers de query (CQRS) idealmente não produzem efeitos colaterais. No entanto, o envio para fila de log é um efeito colateral de observabilidade — não altera o estado do domínio nem da resposta. É fire-and-forget (_ = ...), portanto não bloqueia nem altera o resultado da query.

Esse padrão já é usado em serviços de suporte ao fluxo de pagamento (FinishOrderCommandHandler, FinishPaymentService) e é considerado aceitável pelo time.


Consequências

Positivas

  • Log rastreável por paymentId no AllLogs, visível para suporte.
  • Consistência com o padrão do restante da Checkout API.
  • Fire-and-forget não impacta performance do endpoint.

Negativas / Atenções

  • GetInfoQueryHandler passa a ter uma dependência a mais (ILogQueueService) — quebrando a pureza de query do CQRS.
  • Se a fila AllLogs estiver indisponível, o log é perdido silenciosamente (comportamento padrão da fila).

Mudanças de código implicadas

GetInfoQueryHandler.cs — adicionar ao construtor:

// Campo
private readonly ILogQueueService _logQueueService;

// Parâmetro no construtor
ILogQueueService logQueueService

// Atribuição no corpo do construtor
_logQueueService = logQueueService;

Referências

  • Pesquisa: padrão de uso do ILogQueueService
  • coezzion-service-checkout/src/Checkout.API/Application/Messages/Commands/FinishCommands/FinishOrderCommandHandler.cs
  • coezzion-service-checkout/src/Checkout.Infraestructure/Payment/FinishPaymentService.cs
  • coezzion-service-checkout/src/Checkout.Domain/Events/LogQueueMessageEvent.cs