Files
SQS-service/app/gosqs/queue_attributes.go
T

88 lines
4.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package gosqs
import (
"fmt"
"strings"
log "github.com/sirupsen/logrus"
"shared-sqs/app/models"
)
// setQueueAttributesV1 — применяет атрибуты очереди с валидацией по AWS-спецификации.
//
// Логическая схема:
// 1. Whitelist имён: неизвестное имя атрибута → InvalidAttributeName.
// Список имён (provided) доступен для Query-протокола (form-параметры
// Attribute.N.Name); для JSON-протокола provided == nil и проверка пропускается
// (структура уже разобрана из тела, неизвестные поля отброшены).
// 2. Применяются ТОЛЬКО явно переданные атрибуты (значение != 0).
// ВАЖНО (фикс): раньше условие `attr.X >= 0` срабатывало и для НЕ переданных
// полей (zero-value = 0) — вызов SetQueueAttributes с одним атрибутом
// обнулял все остальные атрибуты очереди.
// 3. Значения вне диапазонов AWS → ошибка InvalidParameterValue
// (раньше значения молча клэмпились в допустимый диапазон).
// 4. RedrivePolicy: ARN DLQ разбирается, DLQ ищется по TENANT-SCOPED ключу
// "{accessKey}:{queueName}" (раньше — по голому имени, а ключи в map
// tenant-scoped → DLQ никогда не находилась, RedrivePolicy не работал).
// DLQ должна принадлежать тому же тенанту.
func setQueueAttributesV1(q *models.Queue, attr models.QueueAttributes, provided map[string]string, tenantAccessKey string) error {
// Шаг 1: whitelist имён атрибутов (единый список — models.AttrNameWhitelist).
for name := range provided {
if !models.AttrNameWhitelist[name] {
return fmt.Errorf("InvalidAttributeName")
}
}
// Шаг 2: применяем только явно переданные атрибуты с проверкой диапазонов.
// Диапазоны AWS: DelaySeconds 0900, MaximumMessageSize 1024262144,
// MessageRetentionPeriod 601209600, ReceiveMessageWaitTimeSeconds 020,
// VisibilityTimeout 043200.
if attr.DelaySeconds != 0 {
if attr.DelaySeconds.Int() < 0 || attr.DelaySeconds.Int() > MaxDelaySeconds {
return fmt.Errorf("InvalidParameterValue")
}
q.DelaySeconds = attr.DelaySeconds.Int()
}
if attr.MaximumMessageSize != 0 {
if attr.MaximumMessageSize.Int() < MinMessageSizeLimit || attr.MaximumMessageSize.Int() > MaxMessageSizeLimit {
return fmt.Errorf("InvalidParameterValue")
}
q.MaximumMessageSize = attr.MaximumMessageSize.Int()
}
if attr.MessageRetentionPeriod != 0 {
if attr.MessageRetentionPeriod.Int() < MinMessageRetentionPeriod || attr.MessageRetentionPeriod.Int() > MaxMessageRetentionPeriod {
return fmt.Errorf("InvalidParameterValue")
}
q.MessageRetentionPeriod = attr.MessageRetentionPeriod.Int()
}
if attr.ReceiveMessageWaitTimeSeconds != 0 {
if attr.ReceiveMessageWaitTimeSeconds.Int() < 0 || attr.ReceiveMessageWaitTimeSeconds.Int() > MaxReceiveMessageWaitTimeSeconds {
return fmt.Errorf("InvalidParameterValue")
}
q.ReceiveMessageWaitTimeSeconds = attr.ReceiveMessageWaitTimeSeconds.Int()
}
if attr.VisibilityTimeout != 0 {
if attr.VisibilityTimeout.Int() < 0 || attr.VisibilityTimeout.Int() > MaxVisibilityTimeout {
return fmt.Errorf("InvalidParameterValue")
}
q.VisibilityTimeout = attr.VisibilityTimeout.Int()
}
// Шаг 3: RedrivePolicy (dead-letter queue).
if attr.RedrivePolicy != (models.RedrivePolicy{}) {
arnArray := strings.Split(attr.RedrivePolicy.DeadLetterTargetArn, ":")
queueName := arnArray[len(arnArray)-1]
// DLQ ищем по tenant-scoped ключу — как хранятся все очереди.
dlqKey := tenantAccessKey + ":" + queueName
deadLetterQueue, ok := models.SyncQueues.Queues[dlqKey]
if !ok {
log.Error("Invalid RedrivePolicy Attribute")
return fmt.Errorf("InvalidAttributeValue")
}
q.DeadLetterQueue = deadLetterQueue
q.MaxReceiveCount = attr.RedrivePolicy.MaxReceiveCount.Int()
}
return nil
}