Files
call-center/docs/runbooks/postgres-dev-cutover.md
T

276 lines
9.6 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.
# 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.