food-market/docs/sprint28-progress.md
nns f6b50baa50
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
docs(s28): сводка interim soak (31min, 91k iter, 0 fail) + overnight work
2026-06-09 03:47:03 +05:00

8.5 KiB
Raw Blame History

Sprint 28 — docs sync + test coverage gap-fill (overnight)

Цель: воспользоваться overnight-окном для накопления реального soak- теста (4 часа), параллельно — мелкие реальные улучшения: точность auto-generated api-reference, новые integration-тесты, CI-integration.

Старт: 2026-06-09 03:15. Исполнитель: Claude Opus 4.7 (autonomous). Продолжение sprint27_done.

Что сделано

1. api-reference.md теперь имеет 240 endpoint'ов (было 195)

ApiReferenceDocsJob regex для return-type'a слишком строгий — матчил только 1-level generic. Не ловил Task<ActionResult<PagedResult<EmployeeDto>>> (double-nested), поэтому пропускал ~45 endpoint'ов.

Фикс: новый regex [^(=;{}\n]+? для return-type (любой identifier с любой глубиной генериков) в:

  • src/food-market.api/Background/ApiReferenceDocsJob.cs (runtime job для weekly auto-gen в /content-root/api-reference-generated.md)
  • scripts/gen-api-reference.py (Python-эквивалент для коммита в репо)

Результат: 240 endpoints, 58 controllers (было 195/57). Пример пропуска: EmployeesController имел 4 из 5 endpoint'ов; теперь все 5 (GET /api/organization/employees был пропущен — это list endpoint с return типом Task<ActionResult<PagedResult<EmployeeDto>>>).

2. observability.md дополнен (Sprint 20+ + Sprint 26)

  • Добавлен ряд про food_market_disk_free_bytes (Sprint 20 DiskMonitoringJob).
  • Новый раздел «quality-watchdog метрики» — 5 метрик textfile exporter'a (quality_watchdog_run_total, step_failure_total, endpoint_p95_ms, last_run_status, incidents_total).
  • Раздел «Готовые dashboards» теперь упоминает оба JSON (food-market.json
    • quality-watchdog.json) с UID/назначением.

3. Integration spec #7: 1C-CSV import + GDPR org-export

tests/integration/07-import-export-flows.spec.ts:

  • POST /api/catalog/products/import/1c-csv с 1С-форматом (Наименование;Штрихкод;Цена;Единица;Группа в semicolon-CSV) → возвращает {created, skipped, errors[], ids[]}.
  • POST /api/org/export (НЕ /api/admin/org-export, как я было предположил — был баг в моих оригинальных предположениях) → возвращает {id, status, ...}.
  • orgB не видит export orgA — multi-tenant clean.

Прогон 8.2s. Pass.

4. PruneQualityTestOrgsAsync unit test

tests/food-market.IntegrationTests/PruneQualityTestOrgsTests.cs — два [Fact]'a:

  • Deletes_only_quality_orgs_older_than_threshold — 4 org'и (старая quality, свежая quality, реальная org, edge-старше-threshold). Threshold 24h. Удаляет 2 (старую quality + edge). Свежая quality и реальная остаются.
  • Returns_zero_when_no_candidates_match — только свежая quality → deleted=0, org остаётся.

Тест требует Testcontainers (PostgreSQL для information_schema + DO блоков) — не SQLite. Прогоняется в CI на dev-vm; локально нет .NET 8.0.417 SDK (global.json pin).

5. Forgejo CI workflow: integration suite

.forgejo/workflows/regression.yml добавлен шаг "Run integration cross-feature suite" после regression flows+visual. На failure артефакты из tests/integration/reports/ тоже загружаются. Telegram-уведомление обновлено: 35 flows + 60 visual + 8 integration.

6. 4-часовой soak test запущен в фоне

setsid nohup k6 run ... & — детачнутая сессия. Параметры:

  • DURATION=4h, RPS=50
  • E2E_ADMIN_URL=stage
  • Output: /tmp/soak-real/k6.log, /tmp/soak-real/summary.json
  • Monitor: 5-минутный snapshot в /tmp/soak-real/metrics.csv

ETA финиша: ~07:15. Финальные числа добавлю в этот файл после завершения.

Soak: интерим-результаты (на момент 03:46, 31 мин run)

Метрика Значение Замечание
iterations 91371 0 interrupted
iter/sec 49.2 target 50 (constant-arrival-rate)
api_mem_mb (range) 250-465 spike 465 — это redeploy для HSTS, нормальное
api_cpu_pct (steady) 54-83% под нагрузкой
pg_connections 19-56 spike 56 во время restart, обратно к 19
disk_free_gb 30 без изменений
products p95 32-256ms 256ms был во время старта (warmup)

Зафиксированы 0 failures (http_req_failed.rate=0.0). Memory не растёт линейно — bounces around 250-300 MiB после warmup.

Soak продолжается до ~07:15. Финальные числа в этом разделе после завершения.

Дополнительная работа (overnight)

После основных 6 пунктов чек-листа также сделано:

7. fix: ApiReferenceDocsJob handle ~/path ASP.NET convention

HttpPost("~/connect/token") — ASP.NET Core конвенция «absolute from root, ignore class [Route]». До фикса генератор клеил с base-route'ом → /~/connect/token (невалидный). Теперь tilde корректно срезается.

Виден /connect/token в api-reference.md.

8. fix(security): HSTS header on stage

Найдено: stage отдавал security-headers (CSP, X-Frame-Options, etc.) но БЕЗ Strict-Transport-Security. Причина: UseHsts() в ASP.NET Core не срабатывает за nginx-прокси (api видит HTTP, не HTTPS — нет ForwardedHeaders middleware'a).

Фикс: добавлен add_header Strict-Transport-Security в deploy/nginx.conf. max-age=2592000 (30 дней), без includeSubDomains и без preload — pre-emptive consent, можно безопасно убрать.

Verified: curl -I https://test.admin.food-market.kz/strict-transport-security: max-age=2592000.

Integration test tests/integration/08-security-headers.spec.ts (2 [Fact]) проверяет 7 security-заголовков на главной + на 404.

9. test: ApiReferenceDocsJob regex lock-down

tests/food-market.UnitTests/ApiReferenceDocsJobTests.cs — создаёт временный controller-файл с double-nested generic (Task<ActionResult<PagedResult<Dto>>>), прогоняет GenerateAsync, проверяет count=3 и наличие всех routes в output.

Защищает от регрессии Sprint 28 fix'a.

10. perf: integration suite workers=2 (46% speedup)

Раньше tests/integration/playwright.config.ts имел workers: 1 из-за signup rate-limit. После Sprint 26 повышения stage до 5000/min — больше не упирается. Включил workers: 2 → прогон 66s → 36s.

11. README + ONBOARDING update до Sprint 28

Sprint history дополнен 25-28. Endpoint count обновлён до 240. Sprint counter unified.

Метрики

До Sprint 28 После Δ
API endpoints в docs/api-reference.md 195 (из 240) 240 +45
Controllers в reference 57 58 +1
Integration specs 6 7 +1
CI integration step (нет) Sprint 27/28 step new
PruneQualityTestOrgs unit test (нет) 2 [Fact]'a new
Observability metrics doc 6 кастомных 11 кастомных (+ disk + 5 watchdog) +5

Артефакты этой ночи

  • scripts/gen-api-reference.py — Python-генератор (соответствует обновлённому ApiReferenceDocsJob.cs)
  • docs/api-reference.md — пересгенерирован, 240 endpoints
  • docs/observability.md — дополнен
  • tests/integration/07-import-export-flows.spec.ts — новый spec
  • tests/food-market.IntegrationTests/PruneQualityTestOrgsTests.cs — новый C# test
  • .forgejo/workflows/regression.yml — added integration step
  • /tmp/soak-real/k6.log, /tmp/soak-real/metrics.csv — soak в процессе