SQS: DeletePersist возвращает ошибку (500 при сбое Redis), fail-fast загрузка очередей, дефолты атрибутов при CreateQueue, защита SqsErrors от nil-deref
This commit is contained in:
@@ -74,7 +74,7 @@ func ChangeMessageVisibilityV1(req *http.Request) (int, interfaces.AbstractRespo
|
||||
if msgRemoved {
|
||||
// Сообщение удалено (перемещено в DLQ) — удаляем из Redis исходной
|
||||
// очереди и сохраняем в DLQ, иначе после рестарта оно пропадёт из DLQ.
|
||||
persistence.DeleteMessagePersist(key, changedMsgUuid)
|
||||
_ = persistence.DeleteMessagePersist(key, changedMsgUuid)
|
||||
if dlqMsg != nil {
|
||||
persistence.SaveMessage(dlqKeyFor(key, queue.DeadLetterQueue.Name), dlqMsg)
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ func ChangeMessageVisibilityBatchV1(req *http.Request) (int, interfaces.Abstract
|
||||
if moved {
|
||||
// Сообщение перенесено в DLQ и удалено из очереди — чистим Redis
|
||||
// исходной и сохраняем в DLQ (иначе пропадёт после рестарта).
|
||||
persistence.DeleteMessagePersist(key, uuid)
|
||||
_ = persistence.DeleteMessagePersist(key, uuid)
|
||||
if dlqMsg != nil {
|
||||
persistence.SaveMessage(dlqKeyFor(key, queue.DeadLetterQueue.Name), dlqMsg)
|
||||
}
|
||||
|
||||
@@ -59,6 +59,13 @@ func CreateQueueV1(req *http.Request) (int, interfaces.AbstractResponseBody) {
|
||||
IsFIFO: utils.HasFIFOQueueName(queueName),
|
||||
EnableDuplicates: models.CurrentEnvironment.EnableDuplicates,
|
||||
Duplicates: make(map[string]time.Time),
|
||||
// Дефолты (как в InitQueues): без них очередь из API получала бы
|
||||
// VisibilityTimeout=0 и т.д. — сообщение сразу видимо, retention 0 = нет
|
||||
// эвикции. Переданные атрибуты перезапишут дефолты в setQueueAttributesV1.
|
||||
VisibilityTimeout: models.CurrentEnvironment.QueueAttributeDefaults.VisibilityTimeout,
|
||||
MaximumMessageSize: models.CurrentEnvironment.QueueAttributeDefaults.MaximumMessageSize,
|
||||
MessageRetentionPeriod: models.CurrentEnvironment.QueueAttributeDefaults.MessageRetentionPeriod,
|
||||
ReceiveMessageWaitTimeSeconds: models.CurrentEnvironment.QueueAttributeDefaults.ReceiveMessageWaitTimeSeconds,
|
||||
// CreatedTimestamp/LastModifiedTimestamp в GetQueueAttributes (AWS их отдаёт).
|
||||
CreatedAt: time.Now().UTC(),
|
||||
LastModifiedAt: time.Now().UTC(),
|
||||
|
||||
@@ -59,8 +59,12 @@ func DeleteMessageV1(req *http.Request) (int, interfaces.AbstractResponseBody) {
|
||||
// ВАЖНО: запись в Duplicates НЕ удаляем — AWS держит dedup-окно 5 минут
|
||||
// независимо от удаления сообщения (иначе повторный send с тем же
|
||||
// dedupId доставлялся бы повторно). Чистит только истечение окна (PeriodicTasks).
|
||||
// Удаляем одно сообщение из Redis — O(1)
|
||||
persistence.DeleteMessagePersist(key, msg.Uuid)
|
||||
// Удаляем одно сообщение из Redis — O(1). Ошибка → 500: иначе клиент
|
||||
// получил бы 200, а после рестарта сообщение «воскресло» бы.
|
||||
if err := persistence.DeleteMessagePersist(key, msg.Uuid); err != nil {
|
||||
log.Errorf("DeleteMessage: не удалось удалить сообщение из Redis: %v", err)
|
||||
return utils.CreateErrorResponseV1("InternalError", true)
|
||||
}
|
||||
// Метаданные очереди (duplicates, FIFO state)
|
||||
persistence.SaveQueue(key, queue)
|
||||
respStruct := models.DeleteMessageResponse{
|
||||
|
||||
@@ -110,8 +110,11 @@ func DeleteMessageBatchV1(req *http.Request) (int, interfaces.AbstractResponseBo
|
||||
deletedUuids = append(deletedUuids, uuid)
|
||||
queue.RemoveIndex(i)
|
||||
}
|
||||
// Удаляем сообщения из Redis отдельно — O(batch_size)
|
||||
persistence.DeleteMessagesPersist(key, deletedUuids)
|
||||
// Удаляем сообщения из Redis отдельно — O(batch_size). Ошибка → InternalError.
|
||||
if err := persistence.DeleteMessagesPersist(key, deletedUuids); err != nil {
|
||||
log.Errorf("DeleteMessageBatch: не удалось удалить сообщения из Redis: %v", err)
|
||||
return utils.CreateErrorResponseV1("InternalError", true)
|
||||
}
|
||||
// Метаданные очереди (duplicates, FIFO state)
|
||||
persistence.SaveQueue(key, queue)
|
||||
|
||||
|
||||
+2
-2
@@ -113,7 +113,7 @@ func processQueueTick(key string, queue *models.Queue) {
|
||||
if len(expired) > 0 {
|
||||
log.Infof("Queue [%s]: evicted %d messages by MessageRetentionPeriod", queue.Name, len(expired))
|
||||
// Удаляем просроченные из Redis, чтобы не воскресли после рестарта.
|
||||
persistence.DeleteMessagesPersist(key, expired)
|
||||
_ = persistence.DeleteMessagesPersist(key, expired)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ func processQueueTick(key string, queue *models.Queue) {
|
||||
queue.RemoveIndex(i)
|
||||
// Персист переноса: иначе после рестарта сообщение «воскреснет»
|
||||
// в исходной очереди (не удалено из Redis) и пропадёт из DLQ.
|
||||
persistence.DeleteMessagePersist(key, msgUuid)
|
||||
_ = persistence.DeleteMessagePersist(key, msgUuid)
|
||||
persistence.SaveMessage(dlqKeyFor(key, dlqName), &dlqMsg)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user