v0.1.35: лимит очередей JWT-тенантов 50, обновление лимита при логине
This commit is contained in:
@@ -519,3 +519,30 @@ DeleteQueue всегда успешен; NextSequenceNumber пересоздаё
|
|||||||
**Проверки**: go build OK (v0.1.35), go vet чистый (кроме известной некомпиляции
|
**Проверки**: go build OK (v0.1.35), go vet чистый (кроме известной некомпиляции
|
||||||
тестов gosqs — пакет fixtures), go test app/models OK.
|
тестов 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
@@ -245,7 +245,7 @@ func (h *Handler) jwtAuth(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Auto-provisioning: тенант и ключи детерминированы из email.
|
// Auto-provisioning: тенант и ключи детерминированы из email.
|
||||||
// Токен — только аутентификация; ключи в ответ не возвращаем (GET /ui/api/credentials).
|
// Токен — только аутентификация; ключи в ответ не возвращаем (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 {
|
if err != nil {
|
||||||
log.Errorf("jwt auth: failed to create tenant: %v", err)
|
log.Errorf("jwt auth: failed to create tenant: %v", err)
|
||||||
jsonErr(w, http.StatusInternalServerError, "failed to provision tenant")
|
jsonErr(w, http.StatusInternalServerError, "failed to provision tenant")
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ import (
|
|||||||
// MaxTenantsGlobal — глобальный лимит тенантов (защита от OOM, Fix #12)
|
// MaxTenantsGlobal — глобальный лимит тенантов (защита от OOM, Fix #12)
|
||||||
const MaxTenantsGlobal = 1000
|
const MaxTenantsGlobal = 1000
|
||||||
|
|
||||||
|
// DefaultTenantMaxQueues — лимит очередей для JWT-тенантов (auto-provisioning).
|
||||||
|
// Используется в app/admin при логине; при каждом логине лимит существующего
|
||||||
|
// тенанта обновляется до этого значения (см. CreateFromJWT).
|
||||||
|
const DefaultTenantMaxQueues = 50
|
||||||
|
|
||||||
// Tenant — модель тенанта shared-sqs.
|
// Tenant — модель тенанта shared-sqs.
|
||||||
// AccessKey используется как идентификатор в AWS Authorization header.
|
// AccessKey используется как идентификатор в AWS Authorization header.
|
||||||
type Tenant struct {
|
type Tenant struct {
|
||||||
@@ -215,6 +220,16 @@ func (s *TenantStore) CreateFromJWT(sub, email string, maxQueues int) (*Tenant,
|
|||||||
if sub != "" {
|
if sub != "" {
|
||||||
existing.NubesSub = 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
|
return existing, nil
|
||||||
}
|
}
|
||||||
// Легаси: убираем старую запись из всех индексов и из Redis, ниже создаём новую
|
// Легаси: убираем старую запись из всех индексов и из Redis, ниже создаём новую
|
||||||
|
|||||||
Reference in New Issue
Block a user