diff --git a/app/admin/admin.go b/app/admin/admin.go index 372c157..b35e8ee 100644 --- a/app/admin/admin.go +++ b/app/admin/admin.go @@ -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") diff --git a/app/tenant/tenant_store.go b/app/tenant/tenant_store.go index 9fdd05d..bf14ec4 100644 --- a/app/tenant/tenant_store.go +++ b/app/tenant/tenant_store.go @@ -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, ниже создаём новую