// Изменено: 2026-04-10 — добавлена Redis persistence // DeleteMessageV1 — удаляет сообщение из очереди тенанта по ReceiptHandle. package gosqs import ( "net/http" "strings" "shared-sqs/app/interfaces" "shared-sqs/app/models" "shared-sqs/app/persistence" "shared-sqs/app/utils" "github.com/gorilla/mux" log "github.com/sirupsen/logrus" ) func DeleteMessageV1(req *http.Request) (int, interfaces.AbstractResponseBody) { requestBody := models.NewDeleteMessageRequest() ok := utils.REQUEST_TRANSFORMER(requestBody, req, false) if !ok { log.Error("Invalid Request - DeleteMessageV1") return utils.CreateErrorResponseV1("InvalidParameterValue", true) } t := getTenantFromContext(req) if t == nil { return utils.CreateErrorResponseV1("InvalidClientTokenId", true) } receiptHandle := requestBody.ReceiptHandle queueUrl := requestBody.QueueUrl queueName := "" if queueUrl == "" { vars := mux.Vars(req) queueName = vars["queueName"] } else { uriSegments := strings.Split(queueUrl, "/") queueName = uriSegments[len(uriSegments)-1] } key := tenantQueueKey(t.AccessKey, queueName) log.Info("Deleting Message, Queue:", queueName, ", ReceiptHandle:", receiptHandle) queue := models.SyncQueues.GetLocked(key) if queue == nil { log.Warning("Queue not found") return utils.CreateErrorResponseV1("MessageDoesNotExist", true) } defer queue.UnlockMu() // O(1)-поиск сообщения по индексу ReceiptHandle → индекс в Messages (P1.2). // Раньше — линейный скан всего среза + сдвиг остатка (O(N) на большое тело). if i, ok := queue.IndexOfReceipt(receiptHandle); ok { msg := queue.Messages[i] // копия ДО мутации: RemoveIndex может сдвинуть срез queue.ClearInFlight(i, receiptHandle) queue.UnlockGroup(msg.GroupID) queue.RemoveIndex(i) // tombstone за O(1) + подрезка хвоста/амортизированная компакция // ВАЖНО: запись в Duplicates НЕ удаляем — AWS держит dedup-окно 5 минут // независимо от удаления сообщения (иначе повторный send с тем же // dedupId доставлялся бы повторно). Чистит только истечение окна (PeriodicTasks). // Удаляем одно сообщение из Redis — O(1) persistence.DeleteMessagePersist(key, msg.Uuid) // Метаданные очереди (duplicates, FIFO state) persistence.SaveQueue(key, queue) respStruct := models.DeleteMessageResponse{ Xmlns: models.BaseXmlns, Metadata: models.BaseResponseMetadata, } return 200, &respStruct } log.Warning("Receipt Handle not found") return utils.CreateErrorResponseV1("MessageDoesNotExist", true) }