feat(shared-sqs): Redis write-through persistence, RollingUpdate deploy (v0.1.11)

This commit is contained in:
“Naeel”
2026-04-10 07:22:41 +03:00
parent ab1e47bd35
commit c9bce7e751
13 changed files with 343 additions and 18 deletions
+4 -3
View File
@@ -1,4 +1,4 @@
// Изменено: 2026-04-09
// Изменено: 2026-04-10 — добавлена Redis persistence
// CreateQueueV1 — создаёт очередь для тенанта из request context.
// Ключ в SyncQueues: "{tenantAccessKey}:{queueName}" для изоляции между тенантами.
package gosqs
@@ -9,6 +9,7 @@ import (
"shared-sqs/app/interfaces"
"shared-sqs/app/models"
"shared-sqs/app/persistence"
"shared-sqs/app/utils"
log "github.com/sirupsen/logrus"
)
@@ -54,8 +55,8 @@ return utils.CreateErrorResponseV1(err.Error(), true)
}
models.SyncQueues.Queues[key] = queue
}
models.SyncQueues.Unlock()
// Сохраняем очередь в Redis пока держим Lock — консистентный снапшот
persistence.SaveQueue(key, models.SyncQueues.Queues[key])
respStruct := models.CreateQueueResponse{
Xmlns: models.BaseXmlns,
Result: models.CreateQueueResult{QueueUrl: queueUrl},
+4 -1
View File
@@ -1,4 +1,4 @@
// Изменено: 2026-04-09
// Изменено: 2026-04-10 — добавлена Redis persistence
// DeleteMessageV1 — удаляет сообщение из очереди тенанта по ReceiptHandle.
package gosqs
@@ -8,6 +8,7 @@ import (
"shared-sqs/app/interfaces"
"shared-sqs/app/models"
"shared-sqs/app/persistence"
"shared-sqs/app/utils"
"github.com/gorilla/mux"
@@ -49,6 +50,8 @@ func DeleteMessageV1(req *http.Request) (int, interfaces.AbstractResponseBody) {
models.SyncQueues.Queues[key].UnlockGroup(msg.GroupID)
models.SyncQueues.Queues[key].Messages = append(models.SyncQueues.Queues[key].Messages[:i], models.SyncQueues.Queues[key].Messages[i+1:]...)
delete(models.SyncQueues.Queues[key].Duplicates, msg.DeduplicationID)
// Сохраняем очередь в Redis пока держим Lock
persistence.SaveQueue(key, models.SyncQueues.Queues[key])
respStruct := models.DeleteMessageResponse{
Xmlns: models.BaseXmlns,
Metadata: models.BaseResponseMetadata,
+5 -1
View File
@@ -1,4 +1,4 @@
// Изменено: 2026-04-09
// Изменено: 2026-04-10 — добавлена Redis persistence
// DeleteQueueV1 — удаляет очередь тенанта по tenant-scoped ключу.
package gosqs
@@ -8,6 +8,7 @@ import (
"shared-sqs/app/interfaces"
"shared-sqs/app/models"
"shared-sqs/app/persistence"
"shared-sqs/app/utils"
log "github.com/sirupsen/logrus"
)
@@ -35,6 +36,9 @@ models.SyncQueues.Lock()
delete(models.SyncQueues.Queues, key)
models.SyncQueues.Unlock()
// Удаляем из Redis асинхронно
persistence.DeleteQueue(key)
respStruct := models.DeleteQueueResponse{
Xmlns: models.BaseXmlns,
Metadata: models.BaseResponseMetadata,
+4 -1
View File
@@ -1,4 +1,4 @@
// Изменено: 2026-04-09
// Изменено: 2026-04-10 — добавлена Redis persistence
// PurgeQueueV1 — очищает все сообщения в очереди тенанта.
package gosqs
@@ -9,6 +9,7 @@ import (
"shared-sqs/app/interfaces"
"shared-sqs/app/models"
"shared-sqs/app/persistence"
"shared-sqs/app/utils"
log "github.com/sirupsen/logrus"
)
@@ -40,6 +41,8 @@ return utils.CreateErrorResponseV1("QueueNotFound", 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)
// Сохраняем пустую очередь в Redis пока держим Lock
persistence.SaveQueue(key, models.SyncQueues.Queues[key])
respStruct := models.PurgeQueueResponse{
Xmlns: models.BaseXmlns,
+4 -1
View File
@@ -1,4 +1,4 @@
// Изменено: 2026-04-09
// Изменено: 2026-04-10 — добавлена Redis persistence
// SendMessageV1 — добавляет сообщение в очередь тенанта.
// Ловушка #6: queueName извлекается как ПОСЛЕДНИЙ сегмент URL — при URL вида
// http://host/tenantID/queueName последний сегмент = queueName (правильно).
@@ -13,6 +13,7 @@ import (
"shared-sqs/app/interfaces"
"shared-sqs/app/models"
"shared-sqs/app/persistence"
"shared-sqs/app/utils"
log "github.com/sirupsen/logrus"
@@ -90,6 +91,8 @@ log.Debugf("Duplicate message deduplicationId [%s] in queue [%s]", messageDedupl
}
models.SyncQueues.Queues[key].InitDuplicatation(messageDeduplicationID)
// Сохраняем очередь в Redis пока держим Lock
persistence.SaveQueue(key, models.SyncQueues.Queues[key])
models.SyncQueues.Unlock()
log.Infof("%s: Queue: %s, Message: %s\n", time.Now().Format("2006-01-02 15:04:05"), queueName, msg.MessageBody)
+4 -1
View File
@@ -1,4 +1,4 @@
// Изменено: 2026-04-09
// Изменено: 2026-04-10 — добавлена Redis persistence
// SetQueueAttributesV1 — устанавливает атрибуты очереди тенанта.
// Ловушка #9: при RedrivePolicy парсим ARN DLQ и DLQ тоже должна принадлежать тому же тенанту.
package gosqs
@@ -9,6 +9,7 @@ import (
"shared-sqs/app/interfaces"
"shared-sqs/app/models"
"shared-sqs/app/persistence"
"shared-sqs/app/utils"
log "github.com/sirupsen/logrus"
)
@@ -45,6 +46,8 @@ return utils.CreateErrorResponseV1("QueueNotFound", true)
if err := setQueueAttributesV1(queue, requestBody.Attributes); err != nil {
return utils.CreateErrorResponseV1(err.Error(), true)
}
// Сохраняем атрибуты в Redis пока держим Lock (через defer)
persistence.SaveQueue(key, queue)
respStruct := models.SetQueueAttributesResponse{
Xmlns: models.BaseXmlns,