528 lines
23 KiB
Markdown
528 lines
23 KiB
Markdown
---
|
||
title: Backend — внешние сервисы и стратегия для test/stage/prod
|
||
---
|
||
|
||
# Backend: внешние сервисы, БД и интеграции
|
||
|
||
> Разбор всех **сторонних зависимостей** `apps/backend`: что они делают, где используются в коде, и **что делать в тестовом контуре** (K8s) — поднять свой инстанс, поставить заглушку или эмулятор.
|
||
>
|
||
> Связанные документы: [K8s + Terraform + ArgoCD + Gitea](./k8s-cicd-platform-plan.md), локальный контур (`local/`, см. корень репозитория), [бизнес-сценарии](../apps/backend-scenarios/index.md).
|
||
|
||
---
|
||
|
||
## 0. Сводная матрица решений (test-контур)
|
||
|
||
| # | Зависимость | Тип | Где в коде | Test-контур | Stage | Prod |
|
||
|---|-------------|-----|------------|-------------|-------|------|
|
||
| 1 | PostgreSQL (основная) | БД | `DATABASE_URL`, Doctrine ORM | **Новый инстанс** (1×) | 1× на stage-сервере | **HA: primary + sync replica** (§7.6 плана) |
|
||
| 2 | PostgreSQL (cabinet) | БД | `DATABASE_CABINET_URL`, `UsrlogController` | **Новый инстанс** + seed | Отдельный | Prod |
|
||
| 3 | MySQL (Bitrix CMS) | БД | `DATABASE_BITRIX_URL`, `BitrixService`, SQL views | **Новый инстанс** + seed из `local/mysql-bitrix` | Отдельный | Prod Bitrix |
|
||
| 4 | Redis | Кеш/сессии | `REDIS_URL` | **Новый инстанс** в K8s | Отдельный | Prod Redis |
|
||
| 5 | MIS / Инфоклиника (HTTP) | API | `MIS_URL`, `InfoclinicaClientService` | **Mock-сервис** (WireMock / свой stub) | Test MIS или read-only prod | Prod MIS |
|
||
| 6 | Widget API (`widget.sovamed.ru`) | API | Hardcoded в Upload*Command | **Mock** или `MIS_URL` после рефакторинга | Stage widget | Prod |
|
||
| 7 | Bitrix site (HTTP, картинки) | API | `BITRIX_URL`, `BitrixClientService` | **Mock** (static files) или seed URLs | Stage | Prod |
|
||
| 8 | SMS (sms.ru, sms4b) | API | `SMSRU_*`, `SMS4B_*` | **Заглушка** (noop) | Заглушка | **Реальный** провайдер |
|
||
| 9 | Почта | API | `MAILER_DSN`, `SendMailService` | **Mailpit / null://null** | Mailpit или sandbox SMTP | Prod SMTP |
|
||
| 10 | Yandex SmartCaptcha | API | `SMARTCAPTCHA_*`, `ServiceController` | **Заглушка** (always OK) | Заглушка | **Реальный** ключ |
|
||
| 11 | Calltouch | API | `CT_*`, `CalltouchController` | **Заглушка** (noop, уже частично) | Заглушка | **Реальный** API |
|
||
| 12 | Bitrix24 | — | `BITRIX24_URL` в `.env` | **Не используется в коде** — игнор | — | При появлении интеграции |
|
||
| 13 | JWT / AES / Lock | Локально | env + файлы ключей | **Свои ключи** test | Свои | Prod secrets |
|
||
| 14 | Symfony Messenger | Очередь | `MESSENGER_TRANSPORT_DSN` | `doctrine://` или `sync://` | doctrine/redis | prod queue |
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph backend [backend pod]
|
||
API[Symfony API]
|
||
CMD[Console / CronJobs]
|
||
end
|
||
|
||
subgraph own_test [Поднимаем в test — свои инстансы]
|
||
PG[(PostgreSQL main)]
|
||
PGC[(PostgreSQL cabinet)]
|
||
MY[(MySQL Bitrix)]
|
||
RD[(Redis)]
|
||
end
|
||
|
||
subgraph stubs [Заглушки в test]
|
||
MIS_M[Mock MIS / Widget API]
|
||
SMS_M[Noop SMS]
|
||
MAIL_M[Mailpit]
|
||
CAP_M[Mock SmartCaptcha]
|
||
CT_M[Noop Calltouch]
|
||
BTX_M[Mock Bitrix HTTP images]
|
||
end
|
||
|
||
subgraph prod_only [Только prod / stage по решению]
|
||
MIS_P[Реальная Инфоклиника]
|
||
SMS_P[sms.ru / sms4b]
|
||
CAP_P[Yandex SmartCaptcha]
|
||
CT_P[Calltouch]
|
||
end
|
||
|
||
API --> PG
|
||
API --> PGC
|
||
API --> MY
|
||
API --> RD
|
||
API --> MIS_M
|
||
API --> SMS_M
|
||
API --> MAIL_M
|
||
API --> CAP_M
|
||
API --> CT_M
|
||
API --> BTX_M
|
||
CMD --> PG
|
||
CMD --> MY
|
||
CMD --> MIS_M
|
||
|
||
MIS_P -.->|stage/prod| API
|
||
SMS_P -.->|prod| API
|
||
```
|
||
|
||
---
|
||
|
||
## 1. Базы данных (с БД — новый инстанс)
|
||
|
||
### 1.1. PostgreSQL — основная (`DATABASE_URL`)
|
||
|
||
**Назначение:** все Doctrine-сущности backend (`User`, `Specialist`, `News`, `Schedule`, …).
|
||
|
||
**Где используется:**
|
||
|
||
- `config/packages/doctrine.yaml` → connection `default`
|
||
- все Repository, миграции `apps/backend/migrations`
|
||
- кеш расписания (`Schedule` в таблице, не Redis)
|
||
- Symfony Messenger при `MESSENGER_TRANSPORT_DSN=doctrine://default`
|
||
|
||
**Test:** Helm Bitnami PostgreSQL / CNPG `instances: 1` в `sova-data-test`.
|
||
|
||
**Stage:** один PG на **отдельном stage-сервере**.
|
||
|
||
**Prod:** Patroni (2 db-VM) + **witness etcd на отдельной VM** (не prod-app). Подключение: `DATABASE_URL` → PgBouncer **:6432** (transaction, API); migrate Job и Messenger → **:5432** (session). [§7.6 плана](./k8s-cicd-platform-plan.md).
|
||
|
||
**Stage/Prod:** отдельные credentials; **никогда** не указывать prod URL в test.
|
||
|
||
---
|
||
|
||
### 1.2. PostgreSQL — cabinet (`DATABASE_CABINET_URL`)
|
||
|
||
**Назначение:** read-only доступ к legacy-таблицам cabinet (не Doctrine entities backend).
|
||
|
||
**Где используется:**
|
||
|
||
- `config/packages/doctrine.yaml` → connection `cabinet`
|
||
- `UsrlogController` — `SELECT` из `public.usrlog` через `doctrine.dbal.cabinet_connection`
|
||
|
||
**Test:** отдельный PostgreSQL (можно второй database на том же chart), seed из `local/postgres/init/03-cabinet-schema-and-seed.sql`.
|
||
|
||
**Если usrlog не нужен в test:** connection можно оставить на пустую БД; эндпоинт `/usrlog/list` вернёт пустой список.
|
||
|
||
---
|
||
|
||
### 1.3. MySQL — Bitrix CMS (`DATABASE_BITRIX_URL`)
|
||
|
||
**Назначение:** чтение таблиц Bitrix (`b_iblock_*`, `b_file`) для синхронизации контента и отзывов.
|
||
|
||
**Где используется:**
|
||
|
||
| Компонент | Как |
|
||
|-----------|-----|
|
||
| `BitrixService` | прямые SQL через `doctrine.dbal.mysql_connection` |
|
||
| `BitrixUpdateReviewsCommand` | `getReviews()` — отзывы по `specialist.id` |
|
||
| `BitrixUpdateDoctorsCommand` | нормализация `dcodes` (Bitrix HTTP закомментирован) |
|
||
| `*CrudService::syncFromView*` | `INSERT … SELECT FROM public.view_*` |
|
||
| Миграции | views `view_article`, `view_news`, … с JOIN на `b_*` (через **mysql_fdw** на prod или упрощённые views в test) |
|
||
|
||
**Test:** **новый MySQL** в K8s (Bitnami MySQL chart), init SQL из `local/mysql-bitrix/init/` в корне репозитория. Дополнительно — создать упрощённые `view_news`, `view_promo`, … или наполнять таблицы `news`/`promo` через CRUD API без sync-команд.
|
||
|
||
**Важно:** на prod PG использует **mysql_fdw** (`infrastructure/pgsql` + extensions). В test можно:
|
||
|
||
- **Вариант A (рекомендуется):** mysql_fdw в test-PG → test-MySQL (повторяет prod);
|
||
- **Вариант B:** отключить sync-команды в test CronJobs, контент только через adminPanel CRUD;
|
||
- **Вариант C:** materialized views только на PG без FDW (дублировать seed в PG).
|
||
|
||
---
|
||
|
||
### 1.4. Redis (`REDIS_URL`)
|
||
|
||
**Назначение:** Symfony cache, sessions (prod php.ini), потенциально Messenger.
|
||
|
||
**Test:** Bitnami Redis в `sova-data-test`, свой пароль в SealedSecret.
|
||
|
||
---
|
||
|
||
## 2. HTTP-интеграции
|
||
|
||
### 2.1. MIS / Инфоклиника (`MIS_URL` → `InfoclinicaClientService`)
|
||
|
||
**Prod URL (пример):** `https://widget.sovamed.ru`
|
||
|
||
**Эндпоинты клиента:**
|
||
|
||
| Метод | Путь | Сценарий |
|
||
|-------|------|----------|
|
||
| GET | `/api/reservation/intervals?{query}` | Расписание врача |
|
||
| GET | `/filials/list` | Список филиалов (через client) |
|
||
| POST | `/api/reservation/anonymous-reserve` | Анонимная запись |
|
||
|
||
**Где вызывается:**
|
||
|
||
- `GetScheduleMessageHandler` → `getSchedule()`
|
||
- `GetAnonymousReserveRequestMessageHandler` → `anonymousReserve()`
|
||
- `UploadDoctorsCommand`, `UploadDepartmentsCommand` → `$client->request('GET', …)` через `InfoclinicaClientServiceInterface`
|
||
|
||
**Test — рекомендация: Mock-сервис в K8s**
|
||
|
||
Развернуть **WireMock** или лёгкий **Node/Go stub** в namespace `sova-mocks`:
|
||
|
||
```text
|
||
MIS_URL=http://mis-mock.sova-mocks.svc.cluster.local
|
||
```
|
||
|
||
Stub должен отдавать JSON в формате, который ждёт `InfoclinicaClientService::normalizeSchedule()` (см. [schedule-cache.md](../apps/backend-scenarios/schedule-cache.md)).
|
||
|
||
**Альтернативы:**
|
||
|
||
| Вариант | Когда |
|
||
|---------|-------|
|
||
| WireMock + JSON fixtures | Полный контроль, воспроизводимые тесты |
|
||
| Отдельный «test MIS» у вендора | Если Infoclinica даёт sandbox (уточнить у владельца интеграции) |
|
||
| Read-only прокси на prod | **Не рекомендуется** — риск записи/нагрузки |
|
||
|
||
**Stage:** sandbox MIS или изолированный контур клиники.
|
||
|
||
---
|
||
|
||
### 2.2. Widget API (hardcoded `https://widget.sovamed.ru`)
|
||
|
||
**Проблема:** часть команд **не читает `MIS_URL`**, а хардкодит URL:
|
||
|
||
| Команда | Путь |
|
||
|---------|------|
|
||
| `UploadFilialsCommand` | `GET /filials/list` |
|
||
| `UploadPriceCommand` | `GET /pricelist/list` |
|
||
| `UploadPriceDepCommand` | `GET /pricelist/departments` |
|
||
|
||
**Test:**
|
||
|
||
1. **Краткосрочно:** тот же mock-сервис, что для MIS, + **рефакторинг команд** — вынести `base_uri` в env `WIDGET_API_URL` или переиспользовать `MIS_URL`.
|
||
2. **До рефакторинга:** mock должен слушать на URL, который прописан в коде (или патч через `/etc/hosts` + Ingress) — **технический долг**.
|
||
|
||
---
|
||
|
||
### 2.3. Bitrix site HTTP (`BITRIX_URL` → `BitrixClientService`)
|
||
|
||
**Prod URL (пример):** `https://sovamed.ru`
|
||
|
||
**Назначение:** скачивание файлов врачей с путей вида `/upload/iblock/...`.
|
||
|
||
**Где используется:**
|
||
|
||
- `GetSpecialistPictureMessageHandler` → `getSpecialistImage($path)`
|
||
|
||
**Test:**
|
||
|
||
| Вариант | Описание |
|
||
|---------|----------|
|
||
| **Mock HTTP** | nginx/static с несколькими `.jpg` в `/upload/iblock/` |
|
||
| **Отключить handler** | Если в test seed картинки уже локальные (`specialist/xxx.jpg`) |
|
||
| **Прокси на stage Bitrix** | Только read, без записи |
|
||
|
||
`BITRIX_URL=http://bitrix-mock.sova-mocks.svc.cluster.local`
|
||
|
||
---
|
||
|
||
### 2.4. SMS — sms.ru и sms4b (`SMSRU_*`, `SMS4B_*`)
|
||
|
||
**Клиенты:** `SmsruClientService`, `Sms4bClientService` (реализуют `SmsClientServiceInterface`).
|
||
|
||
**Статус в коде:** сервисы **зарегистрированы** в `config/services.yaml`, но **ни один контроллер/команда их пока не inject'ит**. Сущности `Record` / `AlertSms` есть, логика отправки SMS **не подключена** к HTTP-сценариям.
|
||
|
||
**Test (по вашему решению): заглушка**
|
||
|
||
```yaml
|
||
# Symfony: test env — noop implementation
|
||
App\Service\Client\Interfaces\SmsClientServiceInterface:
|
||
class: App\Service\Client\Stub\NoopSmsClientService
|
||
```
|
||
|
||
`NoopSmsClientService` пишет в log «SMS suppressed» и возвращает `{ "status": "ok", "stub": true }`.
|
||
|
||
**Prod:** реальные `SMSRU_URL` / `SMS4B_URL` и токены из SealedSecret.
|
||
|
||
**Stage:** заглушка или отдельный «sandbox»-аккаунт провайдера с whitelist номеров.
|
||
|
||
---
|
||
|
||
### 2.5. Почта (`MAILER_DSN`, `SendMailService`)
|
||
|
||
**Где используется:**
|
||
|
||
- `ServiceController::sendmail` — отправка по query-параметрам, защита `MAILER_ACCESS_TOKEN`
|
||
- Symfony `MailerInterface` → `SendMailService`
|
||
|
||
**Prod `.env`:** `MAILER_DSN=null://null` (письма фактически не уходят, но endpoint есть).
|
||
|
||
**Test — рекомендация:**
|
||
|
||
| DSN | Зачем |
|
||
|-----|-------|
|
||
| `smtp://mailpit.sova-mocks:1025` | UI на :8025, видно письма в браузере |
|
||
| `null://null` | Если endpoint `/service/sendmail` не тестируете |
|
||
|
||
**Безопасность Mailpit Web UI:**
|
||
|
||
Mailpit UI (`:8025`) **не выставлять в интернет без защиты**. В тестовых письмах могут быть ФИО, mock-пароли, токены сброса (иногда валидные и на stage).
|
||
|
||
```yaml
|
||
# Ingress mailpit.test.sova.dev — только Basic Auth
|
||
metadata:
|
||
annotations:
|
||
nginx.ingress.kubernetes.io/auth-type: basic
|
||
nginx.ingress.kubernetes.io/auth-secret: mailpit-basic-auth
|
||
nginx.ingress.kubernetes.io/auth-realm: "Mailpit test only"
|
||
```
|
||
|
||
Альтернатива: UI **только cluster-internal** (`kubectl port-forward`), SMTP `:1025` — из `sova-test` по Cluster DNS без Ingress.
|
||
|
||
**Stage:** Mailpit или корпоративный sandbox SMTP.
|
||
|
||
**Prod:** реальный SMTP / API (SendGrid, Yandex 360, …).
|
||
|
||
---
|
||
|
||
### 2.6. Yandex SmartCaptcha (`SMARTCAPTCHA_URL`, `SMARTCAPTCHA_KEY`)
|
||
|
||
**Где используется:**
|
||
|
||
- `ServiceController::smartCaptcha` → `POST /smart-captcha`
|
||
- `AnonymousReserveRequestDto::$captcha` — поле обязательно при записи (валидация на backend)
|
||
|
||
**Test — заглушка:**
|
||
|
||
Mock возвращает `{ "status": "ok", "message": "" }` для любого token (как Yandex при успехе).
|
||
|
||
Или Symfony binding:
|
||
|
||
```yaml
|
||
# when@test
|
||
App\Service\Client\Interfaces\SmartCaptchaClientServiceInterface:
|
||
class: App\Service\Client\Stub\AlwaysValidSmartCaptchaClientService
|
||
```
|
||
|
||
**Prod:** реальный `https://smartcaptcha.yandexcloud.net` + prod key.
|
||
|
||
**Связь с MIS mock:** при `anonymous-reserve` captcha проверяется на backend **до** вызова MIS; mock captcha достаточен для E2E test.
|
||
|
||
---
|
||
|
||
### 2.7. Calltouch (`CT_URL`, `CT_PARAMS`)
|
||
|
||
**Где используется:**
|
||
|
||
- `CalltouchController::createLead` — вызов **`CalltouchClientService::requestCreate` закомментирован**
|
||
- Клиент готов: `POST /lead-service/v1/api/request/create`
|
||
|
||
**Test — заглушка:**
|
||
|
||
- Оставить как сейчас (echo request) **или**
|
||
- `NoopCalltouchClientService` возвращает `{ "data": { "leadId": "test-123" } }`
|
||
|
||
**Prod/Stage (маркетинг):** реальные `CT_URL` + region tokens из `CT_PARAMS`.
|
||
|
||
---
|
||
|
||
### 2.8. Bitrix24 (`BITRIX24_URL`)
|
||
|
||
**Статус:** переменная есть в `.env`, **использований в PHP-коде backend не найдено**. Можно не задавать в test до появления интеграции.
|
||
|
||
---
|
||
|
||
## 3. Локальная инфраструктура (не внешние SaaS)
|
||
|
||
| Переменная | Назначение | Test |
|
||
|------------|------------|------|
|
||
| `JWT_*` | Lexik JWT auth | Сгенерировать отдельную пару ключей для test |
|
||
| `AES_SECRET_KEY` | `AESCryptService` (сущность `Record`) | Случайный ключ 32 байта в Secret |
|
||
| `LOCK_DSN` | Symfony Lock | `flock://` или `postgresql://…` advisory lock |
|
||
| `MESSENGER_TRANSPORT_DSN` | Очередь | `doctrine://default` (таблица messenger_messages) |
|
||
| `CORS_ALLOW_ORIGIN` | adminPanel origins | `https://admin.test.sova.dev` |
|
||
| `API_BASE_URL` | Self-reference / XML feeds | `https://api.test.sova.dev` |
|
||
| `MAILER_ACCESS_TOKEN` | Защита `/service/sendmail` | Случайный UUID в Secret |
|
||
|
||
---
|
||
|
||
## 4. Эталон: что уже сделано локально (`local/.env.local`)
|
||
|
||
В `apps/backend/.env.local` для `sova-local` уже задан паттерн **mock URL**:
|
||
|
||
```dotenv
|
||
MIS_URL=http://mock-mis.local
|
||
BITRIX_URL=http://mock-bitrix.local
|
||
SMS4B_URL=http://mock-sms4b.local
|
||
MAILER_DSN=null://null
|
||
SMARTCAPTCHA_URL=http://mock-smartcaptcha.local
|
||
```
|
||
|
||
**Для K8s test** нужно не просто «мёртвые» hostname, а **реально поднятые mock-поды** + DNS внутри кластера (Service names).
|
||
|
||
---
|
||
|
||
## 5. Архитектура mock-слоя в Kubernetes (test)
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
subgraph sova_test [namespace sova-test]
|
||
BE[backend]
|
||
end
|
||
|
||
subgraph sova_mocks [namespace sova-mocks]
|
||
MIS[mis-mock :8080]
|
||
BTX[bitrix-http-mock :8080]
|
||
CAP[captcha-mock :8080]
|
||
CT[calltouch-mock :8080]
|
||
MP[mailpit :8025]
|
||
end
|
||
|
||
subgraph sova_data [namespace sova-data-test]
|
||
PG[(PostgreSQL)]
|
||
MY[(MySQL Bitrix)]
|
||
RD[(Redis)]
|
||
end
|
||
|
||
BE --> PG
|
||
BE --> MY
|
||
BE --> RD
|
||
BE --> MIS
|
||
BE --> BTX
|
||
BE --> CAP
|
||
BE --> CT
|
||
BE --> MP
|
||
```
|
||
|
||
### 5.1. Рекомендуемые Helm releases (test)
|
||
|
||
| Release | Chart / образ | Назначение |
|
||
|---------|---------------|------------|
|
||
| `mis-mock` | WireMock / custom | расписание, запись, filials, pricelist |
|
||
| `bitrix-http-mock` | nginx + static | `/upload/iblock/*.jpg` |
|
||
| `captcha-mock` | tiny HTTP server | `POST /validate` → ok |
|
||
| `calltouch-mock` | WireMock | lead create |
|
||
| `mailpit` | axllent/mailpit | SMTP + Web UI (**Basic Auth** на Ingress) |
|
||
| `postgresql-test` | bitnami/postgresql | main + cabinet DBs |
|
||
| `mysql-bitrix-test` | bitnami/mysql | Bitrix tables seed |
|
||
| `redis-test` | bitnami/redis | cache |
|
||
|
||
Namespace **`sova-mocks`** общий для всех контуров test (не prod).
|
||
|
||
### 5.2. Env backend test (фрагмент SealedSecret)
|
||
|
||
```yaml
|
||
DATABASE_URL: postgresql://sova_test:***@postgresql-test.sova-data-test:5432/sova_backend_test
|
||
DATABASE_CABINET_URL: postgresql://sova_test:***@postgresql-test.sova-data-test:5432/sova_cabinet_test
|
||
DATABASE_BITRIX_URL: mysql://bitrix_test:***@mysql-bitrix-test.sova-data-test:3306/sova_bitrix_test
|
||
REDIS_URL: redis://:***@redis-test.sova-data-test:6379/0
|
||
MIS_URL: http://mis-mock.sova-mocks.svc.cluster.local:8080
|
||
BITRIX_URL: http://bitrix-http-mock.sova-mocks.svc.cluster.local:8080
|
||
SMARTCAPTCHA_URL: http://captcha-mock.sova-mocks.svc.cluster.local:8080
|
||
SMARTCAPTCHA_KEY: test-key-not-used-by-mock
|
||
SMSRU_URL: http://noop.invalid
|
||
SMS4B_URL: http://noop.invalid
|
||
CT_URL: http://calltouch-mock.sova-mocks.svc.cluster.local:8080
|
||
MAILER_DSN: smtp://mailpit.sova-mocks.svc.cluster.local:1025
|
||
MAILER_ACCESS_TOKEN: "<uuid>"
|
||
CORS_ALLOW_ORIGIN: https://admin.test.sova.dev
|
||
```
|
||
|
||
При внедрении **NoopSmsClientService** URL sms можно не резолвить.
|
||
|
||
---
|
||
|
||
## 6. CronJobs и внешние вызовы
|
||
|
||
| CronJob (из `scripts/cron.*`) | Внешние зависимости | Test |
|
||
|-------------------------------|---------------------|------|
|
||
| `upload:deps`, `upload:doctors` | MIS HTTP | mock MIS или отключить |
|
||
| `upload:filials`, `upload:price*` | widget HTTP (hardcoded) | mock + рефакторинг URL |
|
||
| `bitrix-update-reviews` | MySQL Bitrix | test MySQL + seed |
|
||
| `bitrix-update-doctors` | только PG | OK |
|
||
| `upload:news`, `upload:promo`, … | PG views → MySQL | test MySQL + views или CRUD only |
|
||
| `ClearScheduleCacheCommand` | только PG | OK |
|
||
|
||
**Рекомендация для первого выката test:** включить CronJobs только для **очистки кеша расписания**; sync-команды — после готовности mock MIS и Bitrix MySQL.
|
||
|
||
**concurrencyPolicy в K8s:**
|
||
|
||
Для всех sync CronJobs обязательно:
|
||
|
||
```yaml
|
||
spec:
|
||
concurrencyPolicy: Forbid # не запускать вторую копию, пока первая не завершилась
|
||
jobTemplate:
|
||
spec:
|
||
activeDeadlineSeconds: 3600
|
||
```
|
||
|
||
Без `Forbid` при зависшей БД `bitrix-update-reviews` через час стартует дубликат — параллельные job'ы начнут мешать друг другу.
|
||
|
||
---
|
||
|
||
## 7. Stage vs Prod — отличия от test
|
||
|
||
| Сервис | Test | Stage | Prod |
|
||
|--------|------|-------|------|
|
||
| PostgreSQL / Redis / Bitrix MySQL | Изолированные test DB | Изолированные stage DB | Production DB |
|
||
| MIS | Mock | Sandbox MIS **или** mock | Production MIS |
|
||
| SMS | Noop | Noop или sandbox | Live |
|
||
| Mail | Mailpit | Sandbox SMTP | Live |
|
||
| SmartCaptcha | Mock | Mock | Live |
|
||
| Calltouch | Noop | Noop | Live |
|
||
| Bitrix HTTP (images) | Mock | Stage Bitrix site | Prod |
|
||
|
||
---
|
||
|
||
## 8. Технический долг (сделать до/во время миграции)
|
||
|
||
1. **Hardcoded `widget.sovamed.ru`** в `UploadFilialsCommand`, `UploadPriceCommand`, `UploadPriceDepCommand` → env `WIDGET_API_URL` или `MIS_URL`.
|
||
2. **Hardcoded `https://api.sovamed.ru`** в `XmlFeedGenerator*` → env `API_PUBLIC_URL`.
|
||
3. **Реализовать или явно отключить** SMS-клиенты (`NoopSmsClientService` + bind по env).
|
||
4. **Calltouch** — раскомментировать с env-флагом `CALLTOUCH_ENABLED=false` в test.
|
||
5. **BITRIX24_URL** — удалить из `.env` или документировать при появлении кода.
|
||
6. **Mock-сервисы** — вынести JSON fixtures в репозиторий `sova-mocks` (рядом с `sova-deploy`).
|
||
|
||
---
|
||
|
||
## 9. Чек-лист готовности интеграций test-контура
|
||
|
||
- [ ] PostgreSQL test: миграции backend применены
|
||
- [ ] MySQL Bitrix test: seed + (опционально) mysql_fdw views
|
||
- [ ] Redis test: ping из backend pod
|
||
- [ ] MIS mock: `GET /api/reservation/intervals` возвращает валидный JSON
|
||
- [ ] MIS mock: `POST /api/reservation/anonymous-reserve` → 200
|
||
- [ ] Captcha mock: `POST /validate` → ok
|
||
- [ ] Mailpit: письмо из `/service/sendmail` видно в UI (Basic Auth или port-forward)
|
||
- [ ] SMS: noop binding, приложение стартует без sms.ru
|
||
- [ ] Calltouch: lead endpoint не бьёт prod
|
||
- [ ] CORS: admin.test.sova.dev → api.test.sova.dev
|
||
- [ ] JWT keys: login работает
|
||
- [ ] CronJobs sync: `concurrencyPolicy: Forbid`
|
||
- [ ] CronJobs: только безопасные включены на первом выкате
|
||
|
||
---
|
||
|
||
## 10. Связанные файлы в репозитории
|
||
|
||
| Путь | Содержимое |
|
||
|------|------------|
|
||
| `apps/backend/.env` | prod-like переменные (образец) |
|
||
| `apps/backend/.env.local` | local mock URLs |
|
||
| `apps/backend/config/services.yaml` | DI клиентов |
|
||
| `apps/backend/config/packages/doctrine.yaml` | 3 DB connection |
|
||
| `apps/backend/src/Service/Client/*` | HTTP-клиенты |
|
||
| `apps/backend/src/Service/Bitrix/BitrixService.php` | MySQL Bitrix |
|
||
| `local/mysql-bitrix/init/` | seed Bitrix tables |
|
||
| `local/postgres/init/` | seed PG backend + cabinet |
|
||
| `monitoring/prometheus/prometheus.yml` | scrape Bitrix server `192.168.2.11` (prod-only) |
|
||
|
||
---
|
||
|
||
*Версия 1.0. При изменении интеграций обновлять матрицу в §0 и env-фрагмент в §5.2.*
|