Skip to main content

Схема интеграции Grace CRM → OpenSearch

Версия: 1.0 Дата: 4 мая 2026

Статус: Этап 0 -- согласование файл 02_integration_schema.md


1. Архитектура интеграции

Grace CRM (MySQL) не подключается к OpenSearch напрямую. Синхронизация осуществляется через Sync Agent -- Agno-агент, запускаемый по расписанию или вручную.

Grace CRM (MySQL)    │    │  REST API (GET-запросы)    ▼CLI-команда → Sync Agent (Agno)    │    │  Трансформация данных    │  (нормализация, денормализация, обогащение)    ▼OpenSearch (bulk index)    │    ├── itech_projects    ├── itech_accounts    ├── itech_calculations    ├── itech_orders    ├── itech_order_items    ├── itech_comments    ├── itech_contacts    ├── itech_properties    ├── itech_expected_payments    └── ... (15 индексов)

Важно: прямого доступа к MySQL Grace CRM у Sync Agent нет. Все данные получаются только через REST API Grace CRM.


2. Механизм запуска

2.1 CLI-команда

# Инкрементальная синхронизация (основной режим)grace-sync run --mode incremental​# Полная синхронизация (ночная / восстановление)grace-sync run --mode full​# Синхронизация конкретной сущностиgrace-sync run --entity projects --mode incremental​# Ручной запуск с указанием временного окнаgrace-sync run --mode incremental --since 2026-05-01T00:00:00

2.2 Расписание (cron)

Режим Расписание Описание
Инкрементальный Каждые 15 минут Основной рабочий режим
Полный Ежедневно в 02:00 Восстановление консистентности
Ручной По требованию администратора После миграций, исправлений

3. Сущности и endpoints API

Сущность Endpoint Индекс OpenSearch Частота
Сделки GET /api/projects?updated_since= itech_projects 15 мин
Контрагенты GET /api/clients?updated_since= itech_accounts 15 мин
Расчёты (КП) GET /api/calculations?updated_since= itech_calculations 15 мин
Заказы GET /api/orders?updated_since= itech_orders 15 мин
Позиции заказов GET /api/order_items?updated_since= itech_order_items 15 мин
Активности GET /api/activities?updated_since= itech_comments 15 мин
Задачи GET /api/tasks?updated_since= itech_projects) 15 мин
Контактные лица GET /api/contacts?updated_since= itech_contacts 1 час
Объекты GET /api/objects?updated_since= itech_properties 1 час
Платежи GET /api/expected_payments?updated_since= itech_expected_payments 1 час
Пользователи GET /api/users itech_users 1 раз/день

4. Режимы синхронизации

4.1 Инкрементальный режим

Принцип: запрашиваются только записи, изменённые с момента последней синхронизации.

1. Читаем last_sync_timestamp из хранилища состояния2. GET /api/{entity}?updated_since={last_sync_timestamp}3. Трансформируем полученные записи4. Bulk upsert в OpenSearch (upsert по id)5. Обновляем last_sync_timestamp = текущее время

Хранение состояния: файл sync_state.json или переменная окружения. Формат:

{  "projects": "2026-05-04T08:45:00",  "clients": "2026-05-04T08:45:00",  "orders": "2026-05-04T08:45:00"}

4.2 Полный режим

Принцип: полная выгрузка всех сущностей с пагинацией, полная пересборка индексов.

1. Создаём новый индекс с суффиксом _tmp2. Загружаем все данные через API с пагинацией (batch по 500 записей)3. После успешной загрузки — переключаем алиас4. Удаляем старый индекс

Применяется при: первоначальном развёртывании, восстановлении после сбоя, изменении маппинга.


5. Трансформация данных

5.1 Денормализация

При индексации данные обогащаются связанными сущностями во избежание JOIN-запросов в OpenSearch:

projects → добавляем account_name, manager_name, property_name, project_status (название)orders   → добавляем account_name, manager_name, company_namecomments → добавляем project_name, project_status, account_name, manager_name

5.2 Вычисляемые поля

Поле Индекс Формула
is_shipped itech_orders, itech_order_items shipping_date_fact IS NOT NULL
revenue_mln itech_accounts SUM(order_items.amount) / 1 000 000
debt_mln itech_accounts SUM(expected_payments где paid_amount < pay_amount) / 1 000 000
order_count itech_accounts COUNT(orders.id)
top_account itech_properties Контрагент с наибольшим числом проектов на объекте

5.3 Нормализация данных

  • Имена менеджеров: нормализация пробелов, удаление неразрывных пробелов (\xa0)

  • Даты: приведение к формату yyyy-MM-dd HH:mm:ss

  • Суммы: NULL -> 0.0

  • Булевы поля: 0/1 -> false/true


6. Обработка конфликтов и ошибок

6.1 Стратегия при конфликте версий

Правило: последнее изменение по updated_at побеждает.

# При upsert в OpenSearch{  "doc": { ...новые поля... },  "doc_as_upsert": True}

Если updated_at в новой записи меньше, чем в существующей -- запись не обновляется (idempotent операция).

6.2 Обработка ошибок API

Ситуация Поведение
HTTP 429 (rate limit) Пауза 60 сек, повтор
HTTP 5xx (ошибка сервера) Retry 3 раза с экспоненциальной задержкой
HTTP 404 (запись удалена) Удаление из OpenSearch
Таймаут соединения Retry 3 раза, затем запись в лог ошибок
Частичный сбой батча Повтор только ошибочных записей

6.3 Логирование

Каждый запуск синхронизации фиксирует:

{  "run_id": "uuid",  "mode": "incremental",  "started_at": "2026-05-04T09:00:00",  "finished_at": "2026-05-04T09:00:23",  "entities": {    "projects": { "fetched": 42, "indexed": 42, "errors": 0 },    "orders": { "fetched": 7, "indexed": 7, "errors": 0 }  },  "status": "success"}

7. Мониторинг и алерты

Метрика Пороговое значение Действие
Время последней синхронизации > 30 минут назад Алерт администратору
Количество ошибок за запуск > 5% от batch Алерт + запись в лог
Расхождение счётчиков Индекс < 90% от MySQL Запуск полной синхронизации
Недоступность API Grace > 3 неудачных попытки Алерт + пауза 10 минут

8. Требования к API Grace CRM

Для корректной работы интеграции API Grace CRM должен поддерживать:

Требование Параметр Обязательно
Фильтрация по дате изменения ?updated_since=ISO8601 Да
Пагинация ?page=N&per_page=500 Да
Получение записи по ID GET /{entity}/{id} Да
Аутентификация API-ключ в заголовке Да
Rate limit Информация о лимитах Да (для настройки задержек)

Открытый вопрос: наличие webhooks в API Grace CRM уточняется на Этапе 0. При наличии webhooks -- добавить режим event-driven синхронизации в дополнение к cron-polling.