Pesquisa — Padrão de deduplicação e ordering em fila FIFO (análogo AllLogs)
Data: 2026-06-11
Contexto: Task #196020 — Criar fila SQS FIFO para CartRecommendationsHistory
Objetivo: Definir estratégia de deduplicação e ordering da fila AWS_SQS_CART_RECOMMENDATION_HISTORY_FIFO, análoga ao LogQueueConsumerService.
Fonte analisada
Projeto: coezzion-submodule-message-bus/src/Coezzion.MessageBus/MessageBusService.cs
Consumidor de referência: coezzion-service-checkout/src/Checkout.API/Background/LogQueueConsumerService.cs
Como SendFifoAsync publica mensagens
// MessageBusService.cs — SendFifoAsync (linhas 60-83)
public async Task<bool> SendFifoAsync<T>(string queueUrl, T message) where T : Event
{
sendRequest.MessageGroupId = Guid.NewGuid().ToString(); // UUID aleatório
sendRequest.MessageDeduplicationId = null; // não setado
...
}
Comportamento observado:
MessageGroupId:Guid.NewGuid()— cada mensagem em um grupo diferente, sem ordering entre mensagens do mesmoRecommendationsIdMessageDeduplicationId: não setado — sem deduplicação no nível SQSContentBasedDeduplication: não habilitado na estrutura da fila
Como o LogQueueConsumerService consome e persiste
// LogQueueConsumerService.cs — linhas 43-86
private async Task RegisterConsumer(...)
{
var messageLogs = response.Messages
.Select(m => JsonSerializer.Deserialize<LogQueueMessageEvent>(m.Body))
.ToList();
// Agrupa por schema (multi-tenant), processa, deleta em batch
await messageBusService.DeleteBatchAsync(queueUrl, response.Messages.Select(x => x.ReceiptHandle));
}
Persistência usa x.Timestamp do evento, não DateTime.Now:
// LogQueueConsumerService.cs — linha 104
PaymentsEcommHistoryModel.CreatePaymentsEcommHistory(..., x.Timestamp)
// linha 132/147
PaymentsHistoryAllLogsModel.CreatePaymentsHistoryAllLogs(..., x.Timestamp, ...)
O Timestamp é populado pelo construtor da classe base Event:
// Event.cs
protected Event()
{
Timestamp = DateTime.Now.ToBrazillianTime();
IdEvent = Guid.NewGuid();
}
Ou seja: o timestamp do registro é o momento da publicação pelo producer, não o momento da persistência pelo consumer. A fidelidade temporal é garantida independente da ordem de chegada.
Implicações para CartRecommendationsHistory
Ordenação (MessageGroupId)
A tabela CartRecommendationsHistory é append-only — cada evento é uma linha independente, sem FK entre eventos. O timestamp de cada evento é gravado no momento do publish (via Event.Timestamp), portanto:
- Não há risco de corrupção temporal com
MessageGroupId = Guid.NewGuid() - Não há dependência entre linhas que exija processamento sequencial
- Query de leitura do histórico usa
ORDER BY DateCreated(campoTimestamp), que reflete a ordem real dos eventos
Conclusão: MessageGroupId = RecommendationsId não é necessário para integridade dos dados. Manter o comportamento padr ão do submodule (Guid.NewGuid()) é suficiente.
Deduplicação
O LogQueueConsumerService não utiliza deduplicação na camada de infraestrutura:
MessageDeduplicationIdnão é setado porSendFifoAsyncContentBasedDeduplicationnão está habilitado na estrutura da fila- A proteção contra duplicatas é feita na camada de aplicação (INSERT idempotente / constraint UNIQUE)
Conclusão: seguir o mesmo padrão do AllLogs — sem deduplicação explícita no SQS, proteção na camada de aplicação do consumer (task #196021).
Sumário das decisões
| Aspecto | Decisão | Justificativa |
|---|---|---|
MessageGroupId | Guid.NewGuid() (padrão do submodule) | Timestamp do evento garante fidelidade temporal; tabela append-only não exige ordering |
MessageDeduplicationId | Não setar (padrão do submodule) | Mesmo padrão do AllLogs; proteção de duplicatas na camada de aplicação |
ContentBasedDeduplication | false | Mesmo padrão do AllLogs |
| DLQ | Fora de escopo | Task futura |
Referências
coezzion-submodule-message-bus/src/Coezzion.MessageBus/MessageBusService.cscoezzion-service-checkout/src/Checkout.API/Background/LogQueueConsumerService.cscoezzion-submodule-message-bus/src/Coezzion.MessageBus/Events/Event.cs04-upsell/context/ADR-001-log-queue-service-em-query-handler.md04-upsell/context/pesquisa-log-queue-service-checkout.md