v0.1.35: query-mode XML-ответы, TOCTOU receive, валидации AWS, purge 60s, сужение локов

This commit is contained in:
“Naeel”
2026-08-14 15:53:08 +04:00
parent 8c40ca592f
commit ec10acc99e
15 changed files with 919 additions and 172 deletions
+24 -2
View File
@@ -1,5 +1,3 @@
// Изменено: 2026-04-10 — добавлена Redis persistence
// PurgeQueueV1 — очищает все сообщения в очереди тенанта.
package gosqs
import (
@@ -15,6 +13,21 @@ import (
log "github.com/sirupsen/logrus"
)
// PurgeQueueV1 — очищает ВСЕ сообщения очереди тенанта.
//
// Логическая схема:
// 1. Разбор тела запроса → PurgeQueueRequest.
// 2. Тенант из контекста (SigV4 → AccessKey).
// 3. Имя очереди из QueueUrl (последний сегмент).
// 4. Под Lock:
// - проверка существования очереди → QueueNotFound;
// - защита от повторного purge (фикс): повторный вызов в течение 60 секунд
// → PurgeQueueInProgress (требование AWS). Раньше purge можно было
// вызывать без ограничений;
// - очистка in-memory сообщений и dedup-записей;
// - фиксация LastPurgeTime;
// - асинхронная очистка Redis (DEL хэша сообщений) + SaveQueue.
// 5. Ответ: пустой PurgeQueueResponse.
func PurgeQueueV1(req *http.Request) (int, interfaces.AbstractResponseBody) {
requestBody := models.NewPurgeQueueRequest()
ok := utils.REQUEST_TRANSFORMER(requestBody, req, false)
@@ -39,9 +52,18 @@ func PurgeQueueV1(req *http.Request) (int, interfaces.AbstractResponseBody) {
return utils.CreateErrorResponseV1("QueueNotFound", true)
}
// AWS: PurgeQueue допускается не чаще одного раза в 60 секунд на очередь.
// Нулевой LastPurgeTime (purge ещё не выполнялся) → запрет не срабатывает.
if time.Since(models.SyncQueues.Queues[key].LastPurgeTime) < 60*time.Second {
log.Warnf("Purge Queue: %s rejected — purge in progress (last: %s)", queueName, models.SyncQueues.Queues[key].LastPurgeTime.Format(time.RFC3339))
return utils.CreateErrorResponseV1("PurgeQueueInProgress", true)
}
log.Infof("Purging Queue: %s (tenant: %s)", queueName, t.ID)
models.SyncQueues.Queues[key].Messages = nil
models.SyncQueues.Queues[key].Duplicates = make(map[string]time.Time)
// Фиксируем время purge — защита от повторного вызова в течение 60 секунд.
models.SyncQueues.Queues[key].LastPurgeTime = time.Now()
// Удаляем все сообщения из Redis одной командой DEL
persistence.PurgeMessagesPersist(key)
// Сохраняем пустые метаданные очереди