diff --git a/app/admin/admin.go b/app/admin/admin.go index 153ded3..9d3893a 100644 --- a/app/admin/admin.go +++ b/app/admin/admin.go @@ -14,11 +14,11 @@ import ( "time" "shared-sqs/app/auth" + "shared-sqs/app/gosqs" "shared-sqs/app/models" "shared-sqs/app/persistence" "shared-sqs/app/tenant" - "github.com/google/uuid" "github.com/gorilla/mux" log "github.com/sirupsen/logrus" ) @@ -519,14 +519,9 @@ func (h *Handler) createTenantQueue(w http.ResponseWriter, r *http.Request) { jsonErr(w, http.StatusForbidden, "queue limit exceeded") return } - newQueue := &models.Queue{ - Name: req.Name, - VisibilityTimeout: 30, - MaximumMessageSize: 262144, - MessageRetentionPeriod: 345600, - Messages: []models.SqsMessage{}, - Duplicates: make(map[string]time.Time), - } + // Очередь создаётся через общий билдер — те же URL/ARN/дефолты и FIFO-детект, + // что и в SQS CreateQueue (единый путь, без расхождения поведения UI и API). + newQueue := gosqs.BuildQueueForTenant(t, req.Name) models.SyncQueues.AddQueue(key, newQueue) persistence.SaveQueue(key, newQueue) models.SyncQueues.Unlock() @@ -648,12 +643,15 @@ func (h *Handler) sendMessageToQueue(w http.ResponseWriter, r *http.Request) { jsonErr(w, http.StatusBadRequest, "body is required") return } - msg := models.SqsMessage{ - MessageBody: req.Body, - Uuid: uuid.NewString(), - SentTime: time.Now(), - } + // Сообщение строится через общий билдер (UUID + MD5), + проверка размера — + // как в SQS SendMessage. q.LockMu() + if q.MaximumMessageSize > 0 && len(req.Body) > q.MaximumMessageSize { + q.UnlockMu() + jsonErr(w, http.StatusBadRequest, "message too big") + return + } + msg := gosqs.BuildSqsMessage(req.Body) q.Messages = append(q.Messages, msg) // Персистим одно сообщение отдельно persistence.SaveMessage(key, &msg) diff --git a/app/gosqs/build.go b/app/gosqs/build.go new file mode 100644 index 0000000..7966563 --- /dev/null +++ b/app/gosqs/build.go @@ -0,0 +1,43 @@ +// app/gosqs/build.go +// Общие билдеры очереди и сообщения — чтобы admin/UI-путь создавал объекты +// ровно так же, как SQS API (единый путь, без расхождения дефолтов). +package gosqs + +import ( + "time" + + "github.com/google/uuid" + + "shared-sqs/app/models" + "shared-sqs/app/tenant" + "shared-sqs/app/utils" +) + +// BuildQueueForTenant — создаёт очередь тенанта с теми же URL/ARN/дефолтами и +// FIFO-детектом, что и CreateQueueV1. Используется admin-хендлерами, чтобы +// поведение UI совпадало с SQS API (URL/ARN заполнены, .fifo → IsFIFO). +func BuildQueueForTenant(t *tenant.Tenant, queueName string) *models.Queue { + return &models.Queue{ + Name: queueName, + URL: tenantQueueURL(t, queueName), + Arn: tenantQueueARN(t, queueName), + VisibilityTimeout: 30, + MaximumMessageSize: MaxMessageSizeDefault, + MessageRetentionPeriod: 345600, // 4 дня + IsFIFO: utils.HasFIFOQueueName(queueName), + EnableDuplicates: models.CurrentEnvironment.EnableDuplicates, + Messages: []models.SqsMessage{}, + Duplicates: make(map[string]time.Time), + } +} + +// BuildSqsMessage — создаёт сообщение с UUID, MD5 тела и временем отправки — +// так же, как это делает SendMessageV1 (для admin/UI-пути). +func BuildSqsMessage(body string) models.SqsMessage { + return models.SqsMessage{ + MessageBody: body, + Uuid: uuid.NewString(), + MD5OfMessageBody: utils.GetMD5Hash(body), + SentTime: time.Now(), + } +}