SQS: dedup внутри цикла SendMessageBatch (NextSequenceNumber только для не-дубликата, откат dedup при ошибке персиста, per-entry DelaySeconds)
This commit is contained in:
@@ -127,6 +127,7 @@ func SendMessageBatchV1(req *http.Request) (int, interfaces.AbstractResponseBody
|
|||||||
}
|
}
|
||||||
msg.MD5OfMessageBody = utils.GetMD5Hash(sendEntry.MessageBody)
|
msg.MD5OfMessageBody = utils.GetMD5Hash(sendEntry.MessageBody)
|
||||||
msg.GroupID = sendEntry.MessageGroupId
|
msg.GroupID = sendEntry.MessageGroupId
|
||||||
|
msg.DelaySecs = sendEntry.DelaySeconds
|
||||||
// ContentBasedDeduplication: dedupId вычисляется из тела (SHA-256),
|
// ContentBasedDeduplication: dedupId вычисляется из тела (SHA-256),
|
||||||
// если не передан явно (AWS-семантика FIFO).
|
// если не передан явно (AWS-семантика FIFO).
|
||||||
dedupID := sendEntry.MessageDeduplicationId
|
dedupID := sendEntry.MessageDeduplicationId
|
||||||
@@ -137,17 +138,30 @@ func SendMessageBatchV1(req *http.Request) (int, interfaces.AbstractResponseBody
|
|||||||
msg.Uuid = uuid.NewString()
|
msg.Uuid = uuid.NewString()
|
||||||
msg.SentTime = time.Now()
|
msg.SentTime = time.Now()
|
||||||
|
|
||||||
|
// Дубликат проверяем ДО NextSequenceNumber/Append: иначе seq инкрементировался
|
||||||
|
// бы и для отброшенного дубликата, а два entry с одним dedupID в одном батче
|
||||||
|
// оба добавились бы (InitDuplicatation был после цикла — ревью 2026-10-11).
|
||||||
|
if queue.IsDuplicate(dedupID) {
|
||||||
|
log.Debugf("Duplicate deduplicationId [%s] in queue [%s]", dedupID, queueName)
|
||||||
|
sentEntries = append(sentEntries, models.SendMessageBatchResultEntry{
|
||||||
|
Id: sendEntry.Id,
|
||||||
|
MessageId: msg.Uuid,
|
||||||
|
MD5OfMessageBody: msg.MD5OfMessageBody,
|
||||||
|
MD5OfMessageAttributes: msg.MD5OfMessageAttributes,
|
||||||
|
SequenceNumber: "",
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
fifoSeqNumber := ""
|
fifoSeqNumber := ""
|
||||||
if queue.IsFIFO {
|
if queue.IsFIFO {
|
||||||
fifoSeqNumber = queue.NextSequenceNumber(sendEntry.MessageGroupId)
|
fifoSeqNumber = queue.NextSequenceNumber(sendEntry.MessageGroupId)
|
||||||
}
|
}
|
||||||
if !queue.IsDuplicate(dedupID) {
|
// Регистрируем dedupId сразу — второй entry с тем же id увидит его.
|
||||||
appendedIdx = append(appendedIdx, queue.AppendMessage(msg))
|
queue.InitDuplicatation(dedupID)
|
||||||
newMsgs = append(newMsgs, msg)
|
appendedIdx = append(appendedIdx, queue.AppendMessage(msg))
|
||||||
appendedDedupIDs = append(appendedDedupIDs, dedupID)
|
newMsgs = append(newMsgs, msg)
|
||||||
} else {
|
appendedDedupIDs = append(appendedDedupIDs, dedupID)
|
||||||
log.Debugf("Duplicate deduplicationId [%s] in queue [%s]", dedupID, queueName)
|
|
||||||
}
|
|
||||||
|
|
||||||
sentEntries = append(sentEntries, models.SendMessageBatchResultEntry{
|
sentEntries = append(sentEntries, models.SendMessageBatchResultEntry{
|
||||||
Id: sendEntry.Id,
|
Id: sendEntry.Id,
|
||||||
@@ -166,13 +180,13 @@ func SendMessageBatchV1(req *http.Request) (int, interfaces.AbstractResponseBody
|
|||||||
for _, idx := range appendedIdx {
|
for _, idx := range appendedIdx {
|
||||||
queue.RemoveIndex(idx)
|
queue.RemoveIndex(idx)
|
||||||
}
|
}
|
||||||
|
// Откат dedup-регистраций: иначе retry с тем же dedupId получил бы
|
||||||
|
// «duplicate» без сохранённых сообщений.
|
||||||
|
for _, id := range appendedDedupIDs {
|
||||||
|
delete(queue.Duplicates, id)
|
||||||
|
}
|
||||||
return utils.CreateErrorResponseV1("InternalError", true)
|
return utils.CreateErrorResponseV1("InternalError", true)
|
||||||
}
|
}
|
||||||
// Регистрируем dedupId ТОЛЬКО после успешной записи — иначе ретрай с теми же
|
|
||||||
// dedupId получил бы 200 без сохранённых сообщений.
|
|
||||||
for _, id := range appendedDedupIDs {
|
|
||||||
queue.InitDuplicatation(id)
|
|
||||||
}
|
|
||||||
// Метаданные очереди (FIFO state, duplicates) — без Messages
|
// Метаданные очереди (FIFO state, duplicates) — без Messages
|
||||||
persistence.SaveQueue(key, queue)
|
persistence.SaveQueue(key, queue)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user