P1.2: индексация сообщений — tombstone-удаление O(1), receipt/uuid-индексы, tick по in-flight
- models.Queue: deadIdx/receiptIdx/uuidIdx/liveCount/deadCount + примитивы (AppendMessage/RemoveIndex/Compact/CompactIfNeeded/Reset/EnsureIndexes/ IndexOfReceipt/IndexOfUUID/MarkInFlight/ClearInFlight/InFlightIndexes/LiveCount). Удаление — tombstone за O(1), физическая чистка амортизированная. - DeleteMessage/ChangeMessageVisibility(±Batch): поиск по индексу вместо скана среза; удаление без сдвига остатка. - DeleteMessageBatch: tombstone вместо полной пересборки среза. - processQueueTick: visibility/DLQ по индексу in-flight (O(in-flight)), retention — tombstone, в конце — CompactIfNeeded. - send-пути: AppendMessage + LiveCount (OOM-лимит по живым). - admin/metrics/persistence: учёт живых сообщений, индексы после загрузки из Redis. - Redis-схема не менялась (сообщения и так в per-message HASH).
This commit is contained in:
@@ -73,22 +73,29 @@ func DeleteMessageBatchV1(req *http.Request) (int, interfaces.AbstractResponseBo
|
||||
|
||||
deletedEntries := make([]models.DeleteMessageBatchResultEntry, 0)
|
||||
deletedUuids := make([]string, 0)
|
||||
remainingMessages := make([]models.SqsMessage, 0, len(queue.Messages))
|
||||
|
||||
for _, message := range queue.Messages {
|
||||
if de, found := deleteMessageMap[message.ReceiptHandle]; found {
|
||||
log.Debugf("FIFO Queue %s unlocking group %s:", queueName, message.GroupID)
|
||||
queue.UnlockGroup(message.GroupID)
|
||||
delete(queue.Duplicates, message.DeduplicationID)
|
||||
de.Deleted = true
|
||||
deletedEntries = append(deletedEntries, models.DeleteMessageBatchResultEntry{Id: de.Id})
|
||||
deletedUuids = append(deletedUuids, message.Uuid)
|
||||
} else {
|
||||
remainingMessages = append(remainingMessages, message)
|
||||
// Идём по индексам, не пересобирая срез (P1.2): удаление = tombstone за O(1),
|
||||
// индексы не сдвигаются, поэтому итерация остаётся корректной.
|
||||
for i := range queue.Messages {
|
||||
if queue.IsDead(i) {
|
||||
continue
|
||||
}
|
||||
message := &queue.Messages[i]
|
||||
de, found := deleteMessageMap[message.ReceiptHandle]
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
log.Debugf("FIFO Queue %s unlocking group %s:", queueName, message.GroupID)
|
||||
// Читаем поля ДО RemoveIndex: компакция может перезаписать слот.
|
||||
groupID, dedupID, uuid := message.GroupID, message.DeduplicationID, message.Uuid
|
||||
queue.ClearInFlight(i, message.ReceiptHandle)
|
||||
queue.UnlockGroup(groupID)
|
||||
delete(queue.Duplicates, dedupID)
|
||||
de.Deleted = true
|
||||
deletedEntries = append(deletedEntries, models.DeleteMessageBatchResultEntry{Id: de.Id})
|
||||
deletedUuids = append(deletedUuids, uuid)
|
||||
queue.RemoveIndex(i)
|
||||
}
|
||||
|
||||
queue.Messages = remainingMessages
|
||||
// Удаляем сообщения из Redis отдельно — O(batch_size)
|
||||
persistence.DeleteMessagesPersist(key, deletedUuids)
|
||||
// Метаданные очереди (duplicates, FIFO state)
|
||||
|
||||
Reference in New Issue
Block a user