Initial import with GitLab CI/CD and registry deploy flow
This commit is contained in:
@@ -0,0 +1,275 @@
|
||||
# PostgreSQL Dev Cutover
|
||||
|
||||
Этот runbook описывает безопасный перевод `dev`-окружения с SQLite на PostgreSQL без переноса старых данных.
|
||||
|
||||
## Что считается "без простоя"
|
||||
|
||||
В этом проекте без переноса SQLite-данных безостановочный cutover означает не hot-swap одной и той же базы, а:
|
||||
|
||||
1. поднять новый PostgreSQL-backed stack параллельно;
|
||||
2. прогнать smoke на новом stack;
|
||||
3. переключить dev-трафик на новый gateway;
|
||||
4. оставить старый SQLite stack живым до подтверждения GO;
|
||||
5. при проблеме вернуть трафик обратно без восстановления данных.
|
||||
|
||||
Если сейчас у dev только один instance и нет возможности держать parallel stack, нужен короткий maintenance window.
|
||||
|
||||
## Scope
|
||||
|
||||
Включает:
|
||||
|
||||
- подготовку PostgreSQL и RabbitMQ;
|
||||
- применение SQL migrations;
|
||||
- запуск сервисов в `SCHEMA_MANAGEMENT_MODE=migrations`;
|
||||
- smoke-проверки до и после переключения;
|
||||
- rollback на старый SQLite-backed dev stack.
|
||||
|
||||
Не включает:
|
||||
|
||||
- перенос данных из SQLite;
|
||||
- cleanup legacy SQLite-path;
|
||||
- production cutover.
|
||||
|
||||
## Required Inputs
|
||||
|
||||
- `DEV_GATEWAY_OLD`
|
||||
- `DEV_GATEWAY_NEW`
|
||||
- `POSTGRES_DATABASE_URL`
|
||||
- `APP_TOKEN_SECRET`
|
||||
- `PUBLIC_SWITCH_METHOD`
|
||||
- DNS
|
||||
- reverse proxy
|
||||
- load balancer route
|
||||
- `RABBITMQ_URL`
|
||||
|
||||
Рекомендуемые значения для локально-управляемого dev:
|
||||
|
||||
- `POSTGRES_DATABASE_URL=postgresql://mvp:mvp@<postgres-host>:5432/mvpcc`
|
||||
- `SCHEMA_MANAGEMENT_MODE=migrations`
|
||||
- env template: [\.env.postgres.local.template](/e:/Zhan/.env.postgres.local.template)
|
||||
|
||||
## Phase 0 - Preconditions
|
||||
|
||||
Подтвердить перед началом:
|
||||
|
||||
1. Текущий SQLite-backed dev stack стабилен.
|
||||
2. Перенос данных не нужен.
|
||||
3. PostgreSQL доступен по сети с host, где запускаются сервисы.
|
||||
4. RabbitMQ доступен по сети, если в dev нужен `EVENT_BUS_ENABLED=1`.
|
||||
5. Новая dev-конфигурация использует:
|
||||
- `DATABASE_URL=postgresql://...`
|
||||
- `SCHEMA_MANAGEMENT_MODE=migrations`
|
||||
6. Старый SQLite stack не останавливается до завершения smoke на новом stack.
|
||||
|
||||
## Phase 1 - Preflight
|
||||
|
||||
На будущем PostgreSQL-backed dev host:
|
||||
|
||||
1. Проверить Python зависимости:
|
||||
|
||||
```powershell
|
||||
python -m pip install -r requirements.txt
|
||||
```
|
||||
|
||||
2. Подготовить env-файл:
|
||||
- скопировать [\.env.postgres.local.template](/e:/Zhan/.env.postgres.local.template)
|
||||
- заполнить `DATABASE_URL`, `APP_TOKEN_SECRET`, интеграционные URL и при необходимости AI/Telegram/WhatsApp переменные
|
||||
|
||||
3. Запустить DB-only preflight:
|
||||
|
||||
```powershell
|
||||
python scripts\postgres_dev_preflight.py --env-file .env.postgres.local.template
|
||||
```
|
||||
|
||||
4. Убедиться, что mode не legacy:
|
||||
|
||||
```text
|
||||
SCHEMA_MANAGEMENT_MODE=migrations
|
||||
```
|
||||
|
||||
5. Применить миграции в PostgreSQL:
|
||||
|
||||
```powershell
|
||||
python scripts\migrate_core_db.py
|
||||
```
|
||||
|
||||
Ожидается:
|
||||
|
||||
- миграции применились без ошибок;
|
||||
- в PostgreSQL появилась таблица `schema_migrations`;
|
||||
- сервисы ещё не стартовали.
|
||||
|
||||
## Phase 2 - Bring Up Parallel Stack
|
||||
|
||||
Поднять новый stack параллельно старому.
|
||||
|
||||
Если запуск локальный:
|
||||
|
||||
```powershell
|
||||
python scripts\local_stack.py start `
|
||||
--runtime-dir .local_stack_pg `
|
||||
--env-file .env.postgres.local.template `
|
||||
--force-restart
|
||||
```
|
||||
|
||||
Если это dev server / VM:
|
||||
|
||||
1. развернуть те же сервисы в отдельный deployment set;
|
||||
2. прокинуть им:
|
||||
- `DATABASE_URL=postgresql://...`
|
||||
- `SCHEMA_MANAGEMENT_MODE=migrations`
|
||||
3. не направлять внешний dev-трафик на новый gateway до завершения smoke.
|
||||
|
||||
Важно:
|
||||
|
||||
- новый stack должен использовать отдельный runtime/log directory;
|
||||
- старый SQLite-backed stack остаётся доступным;
|
||||
- нельзя смешивать новый dev-трафик со старым gateway до smoke.
|
||||
|
||||
## Phase 3 - Smoke Before Switch
|
||||
|
||||
Выполнить проверки на `DEV_GATEWAY_NEW`.
|
||||
|
||||
Сначала прогнать HTTP-aware preflight:
|
||||
|
||||
```powershell
|
||||
python scripts\postgres_dev_preflight.py `
|
||||
--env-file .env.postgres.local.template `
|
||||
--base-url http://127.0.0.1:8080
|
||||
```
|
||||
|
||||
1. Health:
|
||||
|
||||
```powershell
|
||||
python scripts\live_smoke_gate12.py --base-url http://<DEV_GATEWAY_NEW> --database-url <POSTGRES_DATABASE_URL>
|
||||
```
|
||||
|
||||
2. Focused PostgreSQL smoke:
|
||||
|
||||
```powershell
|
||||
pytest -q tests/test_postgres_readiness.py
|
||||
```
|
||||
|
||||
3. Дополнительно проверить вручную:
|
||||
|
||||
- `GET /proxy/auth/health`
|
||||
- `GET /proxy/interaction/health`
|
||||
- `GET /proxy/voice/health`
|
||||
- `GET /proxy/ai-voice-runtime/health`
|
||||
- открыть `http://<DEV_GATEWAY_NEW>/operator`
|
||||
|
||||
4. Если в dev включён event bus:
|
||||
|
||||
- проверить подключение к RabbitMQ;
|
||||
- убедиться, что `event-bus-service` поднимается в `healthy`;
|
||||
- убедиться, что новые записи появляются в `event_outbox`.
|
||||
|
||||
GO в следующую фазу только если:
|
||||
|
||||
- health green;
|
||||
- smoke green;
|
||||
- новый stack не пытается auto-create schema на старте;
|
||||
- нет ошибок вида `run python scripts/migrate_core_db.py` после фактического применения миграций.
|
||||
|
||||
## Phase 4 - Traffic Switch
|
||||
|
||||
Переключение выполняется только после успешного Phase 3.
|
||||
|
||||
Рекомендуемый порядок:
|
||||
|
||||
1. уменьшить TTL у dev DNS / подготовить proxy route заранее;
|
||||
2. переключить `DEV_GATEWAY` на `DEV_GATEWAY_NEW`;
|
||||
3. не останавливать старый SQLite stack;
|
||||
4. сразу после switch выполнить быстрый post-switch smoke.
|
||||
|
||||
Примеры post-switch smoke:
|
||||
|
||||
```powershell
|
||||
python scripts\live_smoke_gate12.py --base-url http://<DEV_GATEWAY_PUBLIC> --database-url <POSTGRES_DATABASE_URL>
|
||||
```
|
||||
|
||||
Проверить руками:
|
||||
|
||||
- логин;
|
||||
- создание interaction;
|
||||
- digital thread/message flow;
|
||||
- voice event ingest;
|
||||
- создание voice AI session.
|
||||
|
||||
## Phase 5 - Stabilization Window
|
||||
|
||||
В течение первых 15-30 минут после switch:
|
||||
|
||||
1. наблюдать логи gateway и сервисов;
|
||||
2. следить за ошибками подключения к PostgreSQL;
|
||||
3. следить за ошибками `schema mismatch`;
|
||||
4. следить за ошибками блокировок/unique conflict в voice transcript path;
|
||||
5. сравнивать user-visible поведение со старым dev stack.
|
||||
|
||||
Если всё стабильно:
|
||||
|
||||
1. объявить GO;
|
||||
2. зафиксировать, что `dev` теперь PostgreSQL-backed;
|
||||
3. оставить SQLite stack выключенным, но не удалённым до конца рабочего дня.
|
||||
|
||||
## Rollback
|
||||
|
||||
Rollback делается только через возврат трафика на старый SQLite-backed stack.
|
||||
|
||||
Триггеры rollback:
|
||||
|
||||
- новый gateway не проходит smoke;
|
||||
- сервисы падают на startup;
|
||||
- критичный API path broken;
|
||||
- UI не работает;
|
||||
- ошибки подключения к PostgreSQL не устраняются быстро;
|
||||
- event bus / voice path деградирует.
|
||||
|
||||
Шаги rollback:
|
||||
|
||||
1. вернуть `DEV_GATEWAY_PUBLIC` на `DEV_GATEWAY_OLD`;
|
||||
2. убедиться, что старый SQLite stack всё ещё жив;
|
||||
3. выполнить быстрый smoke на старом stack;
|
||||
4. запретить новый трафик на PostgreSQL-backed stack;
|
||||
5. собрать логи с нового stack.
|
||||
|
||||
Rollback успешен, если:
|
||||
|
||||
- dev UI снова открывается на старом gateway;
|
||||
- CRUD и smoke снова зелёные;
|
||||
- команда работает на старом dev без дополнительных действий.
|
||||
|
||||
## Cutover Sheet
|
||||
|
||||
Перед cutover заполнить:
|
||||
|
||||
- время старта;
|
||||
- кто выполняет switch;
|
||||
- `DEV_GATEWAY_OLD`;
|
||||
- `DEV_GATEWAY_NEW`;
|
||||
- `POSTGRES_DATABASE_URL`;
|
||||
- результат preflight;
|
||||
- результат smoke до switch;
|
||||
- время switch;
|
||||
- результат smoke после switch;
|
||||
- GO / ROLLBACK;
|
||||
- короткий список замечаний.
|
||||
|
||||
## Minimal Command Sequence
|
||||
|
||||
Если нужен самый короткий practical path для dev:
|
||||
|
||||
```powershell
|
||||
python scripts\migrate_core_db.py
|
||||
python scripts\postgres_dev_preflight.py --env-file .env.postgres.local.template
|
||||
python scripts\local_stack.py start --runtime-dir .local_stack_pg --env-file .env.postgres.local.template --force-restart
|
||||
python scripts\postgres_dev_preflight.py --env-file .env.postgres.local.template --base-url http://127.0.0.1:8080
|
||||
pytest -q tests/test_postgres_readiness.py
|
||||
python scripts\live_smoke_gate12.py --database-url postgresql://mvp:mvp@localhost:5432/mvpcc
|
||||
```
|
||||
|
||||
После этого:
|
||||
|
||||
1. переключить dev gateway/public route на новый stack;
|
||||
2. прогнать smoke ещё раз уже через публичный dev URL;
|
||||
3. оставить старый SQLite stack как rollback target.
|
||||
Reference in New Issue
Block a user