v0.1.35: лимит очередей JWT-тенантов 50, обновление лимита при логине

This commit is contained in:
“Naeel”
2026-08-14 16:51:12 +04:00
parent fa237204f0
commit 0b56677363
3 changed files with 43 additions and 1 deletions
+27
View File
@@ -519,3 +519,30 @@ DeleteQueue всегда успешен; NextSequenceNumber пересоздаё
**Проверки**: go build OK (v0.1.35), go vet чистый (кроме известной некомпиляции
тестов gosqs — пакет fixtures), go test app/models OK.
**Ход деплоя и эмпирические уточнения**:
- Первый вариант фикса resolveProtocol («query-mode → XML») оказался НЕВЕРНЫМ:
эмпирика показала, что AWS CLI v2 в query-mode парсит именно JSON-ответы
(list-queues на XML вернул None, на JSON — список). Откачено: протокол ответа
по Content-Type, как было; дефект «Code=None» закрыт правильным форматом
JSON-ошибок {"__type":"com.amazonaws.sqs#Code","message":"..."} в encodeResponse
и GeneralError в actionHandler.
- Whitelist имён атрибутов для JSON-протокола реализован через
QueueAttributes.UnmarshalJSON (единый список models.AttrNameWhitelist);
в whitelist включены FifoQueue/ContentBasedDeduplication (иначе CLI v2
не мог создать FIFO — регрессия была поймана api_test).
- Прод v0.1.35, digest `sha256:7d1c82e9…` (по digest).
**Проверки против прода (v0.1.35)**:
- Пробы ошибок: пустое тело → MissingParameter; max=11 → InvalidParameterValue;
VisibilityTimeout=43201 → InvalidParameterValue; FooBar=1 → InvalidParameterValue;
повторный purge → PurgeQueueInProgress; delete несуществующей → NonExistentQueue;
FIFO без MessageGroupId → MissingParameter. Все с AWS-кодами (Code=None устранён).
- api_test.sh (CLI v2): 22/22 PASS. sdk_test.py (boto3): 15/15 PASS.
- Целостность 25 циклов: с ВМ 25/25 PASS (lost=0, mismatch=0, errors=0).
С локальной машины периодически ReceiptHandleIsInvalid — анализ логов пода
показал: это retry-дубли (первый delete успешен, ответ теряется на пути
клиент→шлюз; сообщение фактически удалено и подбирается следующими циклами).
Инфраструктурная потеря ответов (DDoS-Guard/Nubes gateway), не дефект сервиса.
- smoke.sh: 11/11 PASS.
- 30-мин нагрузочный тест с ВМ — в процессе.
+1 -1
View File
@@ -245,7 +245,7 @@ func (h *Handler) jwtAuth(w http.ResponseWriter, r *http.Request) {
// Auto-provisioning: тенант и ключи детерминированы из email.
// Токен — только аутентификация; ключи в ответ не возвращаем (GET /ui/api/credentials).
t, err := h.store.CreateFromJWT(claims.Sub, claims.Email, 10)
t, err := h.store.CreateFromJWT(claims.Sub, claims.Email, tenant.DefaultTenantMaxQueues)
if err != nil {
log.Errorf("jwt auth: failed to create tenant: %v", err)
jsonErr(w, http.StatusInternalServerError, "failed to provision tenant")
+15
View File
@@ -18,6 +18,11 @@ import (
// MaxTenantsGlobal — глобальный лимит тенантов (защита от OOM, Fix #12)
const MaxTenantsGlobal = 1000
// DefaultTenantMaxQueues — лимит очередей для JWT-тенантов (auto-provisioning).
// Используется в app/admin при логине; при каждом логине лимит существующего
// тенанта обновляется до этого значения (см. CreateFromJWT).
const DefaultTenantMaxQueues = 50
// Tenant — модель тенанта shared-sqs.
// AccessKey используется как идентификатор в AWS Authorization header.
type Tenant struct {
@@ -215,6 +220,16 @@ func (s *TenantStore) CreateFromJWT(sub, email string, maxQueues int) (*Tenant,
if sub != "" {
existing.NubesSub = sub
}
// Обновляем лимит очередей на актуальное значение из кода при каждом
// логине и персистим в Redis — иначе после рестарта пода из Redis
// восстановится старый лимит (было: тенант навсегда оставался с лимитом,
// заданным при первом логине).
if existing.MaxQueues != maxQueues {
existing.MaxQueues = maxQueues
if data, err := json.Marshal(existing); err == nil {
persistence.SaveTenantRaw(existing.ID, data)
}
}
return existing, nil
}
// Легаси: убираем старую запись из всех индексов и из Redis, ниже создаём новую