diff --git a/.gitignore b/.gitignore index 9feac05..9d939b1 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,9 @@ docker/.env.stage /Mnesia.*/ /doc/ +# Локальные учётки admin для Tsung IFT (см. test/tsung/ift-admin.csv.example) +/test/tsung/ift-admin.csv + # Traefik TLS private keys (generated locally for dev/staging). # Никогда не коммитим приватный ключ в репозиторий. docker/traefik/certs/*.key diff --git a/src/handlers/handler_register.erl b/src/handlers/handler_register.erl index 63481d7..a5c0cc3 100644 --- a/src/handlers/handler_register.erl +++ b/src/handlers/handler_register.erl @@ -78,23 +78,14 @@ register(Req) -> % Создаём верификационный токен и отправляем письмо {ok, VerificationToken, _Expires} = core_verification:create_token(User#user.id), logic_email:send_verification_email(Email, VerificationToken), - BaseUser = #{ - id => User#user.id, - email => User#user.email, - role => atom_to_binary(User#user.role, utf8), - status => atom_to_binary(User#user.status, utf8) % <<"pending">> + Response = #{ + user => #{ + id => User#user.id, + email => User#user.email, + role => atom_to_binary(User#user.role, utf8), + status => atom_to_binary(User#user.status, utf8) % <<"pending">> + } }, - %% На стендах (не prod) отдаём verification_token для loadtest/E2E - %% без доступа к почте (IFT EVENTHUB_ENV=stage). - Response = case os:getenv("EVENTHUB_ENV") of - "prod" -> - #{user => BaseUser}; - _ -> - #{ - user => BaseUser, - verification_token => VerificationToken - } - end, handler_utils:send_json(Req1, 201, Response); {error, email_exists} -> handler_utils:send_error(Req1, 409, <<"Email already exists">>); diff --git a/test/tsung/README.md b/test/tsung/README.md index 2c9447a..a5e8e41 100644 --- a/test/tsung/README.md +++ b/test/tsung/README.md @@ -6,42 +6,53 @@ |------|------------| | `eventhub_ift_smoke.xml` | Короткий smoke на IFT после prepare | | `eventhub_ift.xml` | Mix: `auth_browse` 60% + `create_flow` 40%, фазы warmup/ramp/peak | -| `eventhub_tsung.xml` | Legacy localhost (thinktime там в секундах — не использовать для IFT) | +| `eventhub_tsung.xml` | Legacy localhost (не для IFT) | | `eventhub_http.xml` | Legacy короткий localhost | -Цель IFT: **HTTPS** `api.ift.eventhub.local:443` (Traefik). +Цель: **HTTPS** `api.ift.eventhub.local` (+ `admin-api.ift.eventhub.local` для verify). -Auth path: `POST /v1/register` → `POST /v1/verify` → `POST /v1/login`. -На стендах (`EVENTHUB_ENV` ≠ `prod`) register отдаёт `verification_token` (без почты). +### Auth path + +1. `POST /v1/admin/login` (admin-api) — учётка из `ift-admin.csv` +2. `POST /v1/register` → `user.id` +3. `GET /v1/admin/users/:id/verification-token` — спец. admin-метод +4. `POST /v1/verify` +5. `POST /v1/login` → user JWT + +## Подготовка учётки admin + +```bash +# из /opt/eventhub-ift/.env или локальной копии +cp test/tsung/ift-admin.csv.example test/tsung/ift-admin.csv +# одна строка без комментариев: email;password +printf '%s;%s\n' "$ADMIN_SUPER_EMAIL" "$ADMIN_SUPER_PASSWORD" > test/tsung/ift-admin.csv +``` + +`ift-admin.csv` в `.gitignore`. ## Перед прогоном (хост IFT) ```bash -# 1 нода (default) EVENTHUB_REPLICAS=1 bash /opt/eventhub-ift/devops/scripts/ift-loadtest-prepare.sh - -# или N нод -EVENTHUB_REPLICAS=2 bash /opt/eventhub-ift/devops/scripts/ift-loadtest-prepare.sh +# EVENTHUB_REPLICAS=N — больше нод ``` -Оставляет `traefik` + `eventhub×N`, гасит admin-ui / bot / observability / fallback. +Оставляет `traefik` + `eventhub×N`. ## Дех-машина (WSL) -1. DNS: `api.ift.eventhub.local` → IP IFT (тот же, что в OpenWRT). -2. Установка: `sudo apt install tsung` (или [документация Tsung](http://tsung.erlang-projects.org/)). -3. TLS: самоподписанный сертификат стенда — импортировать CA из `EventHubDevOps/ift/traefik/certs` в trust store WSL, либо временно положить CA в `/usr/local/share/ca-certificates/` и `update-ca-certificates`. Проверка: `curl -sf https://api.ift.eventhub.local/health`. -4. Запуск из корня `EventHubBack`: +1. DNS: `api.ift.eventhub.local` и `admin-api.ift.eventhub.local` → IP IFT. +2. `sudo apt install tsung` +3. TLS: доверить CA стенда (`EventHubDevOps/ift/traefik/certs`). Проверка: + `curl -sf https://api.ift.eventhub.local/health` +4. Из корня `EventHubBack`: ```bash -# smoke (~1 мин) tsung -f test/tsung/eventhub_ift_smoke.xml start - -# полный прогон (~6 мин фаз) tsung -f test/tsung/eventhub_ift.xml start ``` -Отчёт: `~/.tsung/log//` → `tsung_stats.pl` / HTML. +Отчёт: `~/.tsung/log//`. ## После прогона @@ -51,11 +62,10 @@ bash /opt/eventhub-ift/devops/scripts/ift-loadtest-restore.sh ## Настройка интенсивности -В `eventhub_ift.xml` блок ``: `interarrival` (сек между стартами пользователей) и `duration` фаз. -`thinktime` — **секунды** (не мс). +В `eventhub_ift.xml` блок ``: `interarrival` и `duration` фаз. +`thinktime` — **секунды**. -## Что сознательно убрано из hot path +## Замечания -- dummy `/v1/refresh` -- reports / tickets (шум модерации) -- завышенные thinktime (старый `eventhub_tsung.xml`) +- Каждый VU делает admin login — это нагрузка и на admin-api; при необходимости позже вынести общий admin JWT в csv. +- Из hot path убраны: dummy refresh, reports/tickets, завышенные thinktime старого `eventhub_tsung.xml`. diff --git a/test/tsung/eventhub_ift.xml b/test/tsung/eventhub_ift.xml index 68cc581..3e7e31d 100644 --- a/test/tsung/eventhub_ift.xml +++ b/test/tsung/eventhub_ift.xml @@ -2,8 +2,8 @@ @@ -29,22 +29,46 @@ + + + + - + + HTTP/1.[0-1] 20 + + + + + + HTTP/1.[0-1] 20 + + + HTTP/1.[0-1] 20 + + + + + + HTTP/1.[0-1] 20 + + + + @@ -104,13 +132,32 @@ - + + HTTP/1.[0-1] 20 + + + + + + HTTP/1.[0-1] 20 + + + HTTP/1.[0-1] 20 + + + + + + HTTP/1.[0-1] 20 @@ -22,10 +22,15 @@ + + + + @@ -33,14 +38,35 @@ + - + + HTTP/1.[0-1] 20 + + + + + + HTTP/1.[0-1] 20 + + + + HTTP/1.[0-1] 20 + + + + + + HTTP/1.[0-1] 20