Files
EvoBGP/docs/backend-baseline.md
T
DenozordecandCursor 240d83fc61 docs(docs): describe durable jobs, telemetry, and bundle limits
Зафиксированы очередь job, семантика метрик, лимиты бандла и исходящих запросов, а также чеклист продакшена для пула соединений.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-02 17:24:18 +07:00

102 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Backend: исходные измерения и воспроизведение проблем
Материалы этапа 0 [плана развития](backend-improvement-plan.md). Сборщик ниже выполняет только чтение Docker; он не запускает, не останавливает и не обновляет сервисы, не вызывает refresh/apply и не подключается к production автоматически.
## Ресурсный snapshot
На машине с Docker daemon и PowerShell выполните из корня репозитория:
```powershell
./scripts/collect-backend-baseline.ps1 -ComposeFile @('deploy/compose/docker-compose.yaml', 'deploy/compose/docker-compose.microvps-full.yaml') -Profile microvps-full -Samples 3 -IntervalSeconds 15
```
Укажите те же Compose-файлы, profile и при необходимости `-ProjectName`, с которыми запущен исследуемый стек. Относительные Compose-пути разрешаются от корня репозитория. Для другого окружения передайте его файлы явно. Скрипт работает с **текущим Docker context**; перед запуском проверьте, что выбран нужный хост.
Результат по умолчанию записывается в игнорируемый Git каталог `artifacts/backend-baseline/`; другой путь задаётся `-OutputPath`. Код выхода `0` означает собранные snapshots работающих контейнеров, `2` — неполный результат или недоступную среду. Статусы `partial/unavailable` нельзя считать успешным замером. `configured_services` содержит определения из effective config (включая другие profiles, если их возвращает Compose), а `containers` — фактически найденные контейнеры выбранного проекта. Нельзя суммировать всю конфигурацию как реально запущенный workload.
Сохраняются только разрешённые поля: commit, image references/IDs, Docker version, CPU/RAM хоста, настроенные/фактические resource limits, OOM/restart counters и результаты `docker stats`. Raw Compose config разбирается только в памяти. Environment, commands, labels, mount paths, логи и текст ошибок Docker не записываются. Сам отчёт всё равно содержит инфраструктурные метаданные; перед публикацией его нужно проверить.
Это точечные значения CPU/memory и накопительные IO counters, а не p95/p99, peak RSS или нагрузочный benchmark. Отдельно зафиксируйте dataset (число модулей/префиксов/узлов), workload, длительность, BGP-сессии, API latency, DB waits, PSI и cgroup events по D00. Для delta IO сравнивайте один и тот же container ID без restart; новое значение counters после пересоздания не означает снижение нагрузки. Объём образа/слоёв, pull/build time и 24h soak пока собираются отдельно.
## Регрессионные проверки достоверности live-status
```powershell
go test ./internal/httpapi -run '^TestStage0Repro' -count=1 -v
```
После исправления S01 build tag удалён: эти тесты входят в обычный обязательный набор. Проверяются сохранённый Established при timeout/отсутствующей сессии/collector и ложный healthy у неопрошенного master. Дополнительные проверки в `peers_live_test.go` подтверждают, что успешный опрос постороннего speaker не превращает неизвестное состояние назначенного speaker в `absent` или `ok`. Это локальные регрессии HTTP-слоя; они не заменяют стенд с реальными агентами.
## Статус фактической проверки этапа 0
### Дополнение: legacy 2.56.2 и durable jobs
Обязательная версия удалённых speakers уточнена пользователем: **2.56.2**. Тег `v2.56.2` разрешён в commit `924f111e4871e1d6d47c9916d7da1b9051718f1c`. На Windows собраны исторические node/agent без изменения их исходников. Node прошёл pull/auth/signature против текущего HTTP API, включая отказ на неверном ключе подписи; agent serve прошёл dispatch/ACK/health/protocols с текущим подписанным bundle и fake BIRD. Дополнительный CLI v1.0.0 также прошёл проверку. Это source-built executables, не опубликованные Docker images и не настоящий BIRD/TLS стенд.
CI-скрипт `scripts/ci/legacy-node-compatibility.sh` закрепляет commits и проверяет отсутствие skips нужных binary tests. `scripts/tests/mirror-base-images.test.sh` локально прошёл восемь offline сценариев; он не измеряет загрузку или сборку Docker.
Тест отчёта jobs подтверждает чтение durable speaker progress новым Registry, собственный результат recovery вместо старого результата родителя и изоляцию tenant. PostgreSQL-проверки lease/generation/restart и fresh seed добавлены в обязательный CI gate; локально без DSN результат остаётся неподтверждённым.
После добавления отчёта выполнены `go test ./... -count=1`, `go vet ./...`, `scripts/lint-go.ps1`, OpenAPI lint/codegen и frontend typecheck/lint/build — exit 0. После финального исправления порядка health observations повторены тесты затронутых пакетов и legacy binaries 2.56.2 — exit 0. Astra завершила проверку очереди, fencing, health token, отчёта и fixture pruning без оставшихся блокирующих замечаний. Реальный SQL/race gate не выполнен локально; обязательных CI DB/repository tests теперь 17.
### Дополнение: разделение внешних HTTP pools
Восстановление прежнего доступа к настроенным private DoH/RIPE явно разрешено пользователем после первоначального отказа автоматической проверки. Политика и границы описаны в [outbound-policy-decision.md](outbound-policy-decision.md). Тест actual bootstrap DOMAINS refresh с локальным DoH прошёл; CDN через paired client сохраняет public-only guard. Три последовательных TLS CDN-запроса используют одно соединение.
До начала S02 полный Go test, lint-go и legacy 2.56.2 binary smoke прошли. Astra независимо прогнала RIPE/DoH/CDN/breaker тесты четырёх пакетов. Bounded breaker cache проверен на capacity1024, active/open retention, metric cleanup и 253-символьный hostname с завершающей точкой. Production DNS/network policy и реальные ресурсы хоста не проверялись.
### Дополнение: HTTP admission и квоты
После добавления общего 8 MiB body preflight, четырёх body slots и tenant/global квот preview/lookup выполнены OpenAPI lint/codegen, frontend typecheck/lint/build, `scripts/lint-go.ps1` и повторный полный `go test ./... -count=1` — exit 0. Legacy node/agent 2.56.2 повторно прошли HTTP/dispatch compatibility tests. Astra независимо проверила auth-first, отмену без преждевременного освобождения слота, Retry-After/CORS, ограниченный CDN error-body и отсутствие изменений legacy GET/SSE.
Первый полный прогон выявил нестабильность очереди при равном CreatedAt. Исправлен tie-breaker RequestSequence/ID; детерминированная regression с одинаковым временем прошла 50 повторов у Astra, jobs/store — 20 у Sol. После исправления полный прогон и lint прошли. Реальный PostgreSQL/race и нагрузочные RSS/CPU измерения этим не заменяются.
### Дополнение: B05 CSV и bundle limits
CSV byte/row/field preflight, отсутствие записи при превышении и отмена прошли focused tests и независимую проверку Astra. Полный `go test ./... -count=1`, Go lint и frontend gates прошли после добавления CSV/bundle limits; после финальных sparse/retry-body исправлений повторены bundle/nodecli/httpclient/pipeline tests и проверка старых node/agent 2.56.2 — exit 0. OpenAPI lint/codegen также успешны.
Windows-проверка extraction выполнила hard-link часть, затем получила `SKIP` при создании symlink из-за отсутствия привилегии. Это не подтверждение symlink runtime safety: на Linux тест не допускает такой skip и должен пройти в обычном CI `go test -race`. Конфигурация из миллиона повторяющихся IPv6 route-строк проверяет допустимый размер bundle, а не BIRD или производительность реального миллиона уникальных маршрутов.
В локальной среде 26.10.2026 доступны Go 1.26.1 и golangci-lint; Docker/psql и C-компилятор в PATH не найдены, `CGO_ENABLED=0`. Поэтому production-ресурсы, реальный PostgreSQL integration и Go race detector здесь не подтверждены. CI использует проектную версию Go; результаты локального более нового Go не заменяют этот прогон. Конкретные выполненные проверки и оставшиеся gates фиксируются в [статусе плана](backend-improvement-plan.md).
| Проверка 26.10.2026 | Результат |
|---|---|
| `go test ./... -count=1` | Exit 0; повторный полный прогон после добавления тестов. DB-тесты без DSN пропущены. Для тестовых localhost-серверов потребовался запуск вне sandbox |
| `go vet ./...` | Exit 0 |
| `pwsh -NoProfile -File scripts/lint-go.ps1` | Exit 0 после исправления области поиска файлов и замечаний errcheck в новых тестах; выполняет gofmt check, vet и golangci-lint |
| `pwsh -NoProfile -File scripts/tests/collect-backend-baseline.test.ps1` | Exit 0; offline mock, проверены несколько контейнеров, whitelist без секретов и partial/exit 2 при отсутствии stats |
| JSON guard PostgreSQL CI | На синтетических событиях: полный pass принят; skip, пропущенный обязательный тест и подмена subtest отклонены. Сам PostgreSQL job локально не запускался |
| `go test ./internal/httpapi -run '^TestStage0Repro' -count=1 -v` | После S01 включён в основной набор; ожидается exit 0. Первоначально opt-in тесты воспроизводили дефекты, теперь закрепляют исправленное поведение |
| `go test ./... -race -count=1` | Не выполнен: race требует CGO и отсутствующий C toolchain. Проверка остаётся обязательной в CI |
| Resource collector без Docker | Сформирован `status=unavailable`, причина `docker-cli-unavailable`; никаких чисел VPS из этого запуска не получено |
| Повторная проверка Astra | Замечания к guard обязательных DB-тестов и полноте stats исправлены; оставшихся блокирующих замечаний в проверенном diff нет |
### Runtime-итерация B01/B02/S01
- Полный `go test ./... -count=1` после первой runtime-итерации: exit 0 вне sandbox для localhost-тестов. PostgreSQL без DSN по-прежнему пропускается.
- После замечаний Astra повторный `go test ./internal/birddeploy ./internal/jobs ./internal/nodedispatch ./internal/httpapi -count=1`: exit 0. Проверены исправления include scanner, отмена dispatch и старый пустой ответ 204.
- Повторный review Astra не выявил блокирующих замечаний в исправлениях B01/B02/S01. В UI замечания по знаменателям deployment/peer KPI и явному unhealthy исправлены и покрыты регрессиями; повторный review без блокеров.
- UI: `pnpm --filter @evobgp/web run typecheck`, `lint`, `build` — exit 0; Vitest — 9/9. В lint сохраняется существующий warning `use-file-upload.ts`. Визуальный прогон в браузере не выполнялся.
- `pwsh -NoProfile -File scripts/lint-go.ps1` после исправлений B01/B02/S01 — exit 0 (gofmt, vet, golangci-lint).
- B02 Linux-тесты компилируются, но не запускались локально. CI `bird2` дополнен реальным `bird -p`; configure в этом тесте имитируется. Это не проверка работающего BIRD daemon, сетевых сессий или полного восстановления после аварии процесса.
- Новый apply требует существующий parse-valid `ActiveDir/bird.conf` как LKG. Управляемые include должны быть отдельными строками и ссылаться внутрь `bird.d`; внешние/вложенные/неподдержанные include отклоняются до переключения. Старый удалённый агент продолжает применять прежний bundle своим кодом; ограничение относится к обновлённому локальному apply.
- B05 transport/proxy и B02 symlink hardening: повторный полный `go test ./... -count=1` — exit 0; scoped tests, `go vet ./...` и `scripts/lint-go.ps1` — exit 0. Astra не нашла блокеров в проверенном diff.
### Следующая очередь: B04 migrations / S06 / CDN body
- После изменений полный `go test ./... -count=1` — exit 0. После финальных замечаний Astra тесты изменённых пакетов (`db`, `observability`, `repository`, `store`, `pipeline`, `httpapi`) — exit 0; последние lexical-guard регрессии дополнительно проверены `go test ./internal/db -count=1`. DB integration без DSN пропущены и не считаются пройденными.
- Общий `scripts/lint-go.ps1` — exit 0; OpenAPI lint — exit 0 с прежним предупреждением о неиспользуемой `FirewallRule`; `git diff --check` и shell syntax CI guard — exit 0.
- CDN: добавлен настоящий TLS HTTP redirect с контролируемым DNS/dial, проверяющий отказ до соединения с private target. Exact-limit/overflow, ingest/preview и gzip tests прошли; данные больше 8 MiB не парсятся частично. Реальный внешний DNS/production при этом не использовался.
- S06: проверены отсутствие ложных нулей при ошибке БД, сохранение legacy labels и нормализация только нового ряда. Desired/published/applied/live метрики остаются следующей работой.
- B04: 33 существующих PostgreSQL migration-файла проходят проверку transaction-only policy. Новые DB-тесты используют изолированные схемы; CI guard требует все 23 обязательных DB/repository tests. Повторный review Astra закрыл обходы через комментарии, dollar-identifiers и E-string boundaries. Реальный PostgreSQL, race и Linux BIRD всё ещё требуют соответствующего окружения.
CI-запуск для подготовленной изолированной тестовой БД на Linux: задать `EVOBGP_TEST_DATABASE_URL`, затем `bash scripts/ci/postgres-integration.sh`. Использовать только отдельную тестовую БД: тесты применяют миграции и выполняют CRUD/prune. Не указывать production DSN. В Gitea job эта БД создаётся service-контейнером PostgreSQL 16; 23 обязательных DB/repository tests исполняются последовательно с `-race` и проверкой событий pass/skip/fail.
## PostgreSQL runtime: Windows, 26 октября 2026
На отдельном временном кластере PostgreSQL **16.15** выполнены все **23 обязательных** DB/repository integration tests из `scripts/ci/postgres-integration.sh`: обе группы PASS, 0 skip, 0 fail. Проверены миграции и код до **000036 включительно**, до начала добавления manifest migration 000037. Сценарии включают competing migration locks/rollback, durable queue/deployment leases, telemetry discovery rollback и snapshot transaction cancellation/concurrency/partial write/потерю backend-соединения.
Прогон использовал `go test -count=1 -p 1 -json`: DB-фильтр `^TestPostgresMigration.*Integration$`, repository-фильтр `Integration$`. Все 23 именованных pass проверены по JSON-логам независимо от exit code пакетов. Это Windows-прогон **без `-race`**; обязательный Linux/race CI остаётся отдельным gate.
Portable runtime взят из [официального архива EDB](https://www.enterprisedb.com/download-postgresql-binaries), файл `postgresql-16.15-5-windows-x64-binaries.zip`; SHA-256 проверен по vendor `.sha256`: `43bb45f173a6f08cf1d29a97a6d8deb119e8e8093a24c00d2d1001a0ccaa8281`. Кластер слушал только `127.0.0.1` на свободном порту с временным паролем. Служба Windows не создавалась; после тестов `pg_ctl status` подтвердил отсутствие работающего сервера. Локальные JSON-логи сохранены в ignored `artifacts/backend-baseline/pg-test-5c93b7da43dc4c488ca7796a686213c2/`.