Files
han-app/modules/sync-service-concept.md
T

21 KiB
Raw Blame History

Статус: исходный концепт и история обсуждения. Каноническая реализационная постановка после принятия решений — module-07-bitrix-sync.md. При расхождении применяется module-07.

Актуализация 2026-08-06: production-проверка reconciliation использует crm.item.list, entityTypeId=3, фильтры >=updatedTime, opened=1, ufCrm_1778692456=1. Указанные ниже ранние варианты UF_CRM_6A70C275346A7, Y/N и поиск по двум телефонным маскам сохранены только как история и не являются реализационным контрактом.

MCP Server Bitrix24 с документацией https://mcp-dev.bitrix24.tech/mcp

1. Границы релиза

1.1. Что входит в первый релиз sync: contact.map_or_create, contact.update, передача в Битрикс24 тэга о том, что пользователь зарегистрирован в приложении webhook Bitrix→App при изменении данных у пользователей, зарегистрированных в приложении обновление сведений о данных пользователя при изменении их в Битрик24, ведение бизнес-логов с конфликтами и ошибкам, требующих внимания. создание и отслеживание статуса alerts по конфликтам

1.2. Что явно вне scope: Lead/Deal, документы компании в профиль, merge контактов, ручной replay API

1.3. Можно ли выпускать без двусторонности (только App→Bitrix), или webhook обязателен сразу? вебхук обязателен в первой сборке

2. Сущности и маппинг полей

2.1 Какие поля ClientProfile / UserIdentity синхронизируем (в скобках поле в битрикс24): full_name ↔ name citizenship ↔ ufCrm_1768493029, russian_phone ↔ phone, email ↔ email

Значение citizenship возвращается ИД. Справочник Битрикс можно загрузить curl -sS -G 'https:///rest///crm.contact.userfield.list'
--data-urlencode 'filter[FIELD_NAME]=uf_crm_1768493029'

При запросах важно соблюдать следующий принцип: сервис проектируется таким образом, чтобы запрашивать минимум необходимой информации. Т.е. а) если мы синхронизинуем 5 полей, то мы запрашиваем ровно 5 нужных полей. Не запрашиваем все данные по клиенту. б) если нам надо синхронизировать контакт по телефону - мы ищем в Б24 контакт только по этому телефону. Не запрашиваем список контактов.

Второй момент, выявленный в ходе тестирования: Номер телефона может храниться в двух форматах - "+7xxxxxxxxxx", "+7 (xxx) xxx-xxxx" Соответственно, по каждому искомому телефону делаем запрос по двум маскам, указанным выше.

Также сервис следует проектировать с учетом ограничений Битрикс24 по кол-ву обращений к АПИ (генерируем очередь и делаем запросы по расписанию через batch).

Пример запроса требуемых данных для одного пользователя: curl -X POST
-H "Content-Type: application/json"
-H "Accept: application/json"
-d '{"entityTypeId":3,"select":["id","name","phone","ufCrm_1768493029","createdTime"],"filter":{"@phone":["+7xxxxxxxxxx","+7 (xxx) xxx-xxxx"],"opened":"Y"}}'
https:///rest///crm.item.list

2.2. Нужен ли флаг «контакт зарегистрирован в приложении» в Bitrix, и в каком поле? Нужен (поле UF_CRM_6A70C275346A7: Y/N).

3. Правила матчинга Contact

3.1. Ключ поиска: только телефон (как выше указывал телефон хранится по одной из двух масок; возможно в документации есть более стабильные методы поиска контакта по номеру телефона)

3.2. Управление конфликтами: Для разбора конфликтов должны создаваться alert: задача в Б24 (смарт процесс "Конфликты синхронизации") и бизнес-лог в БД с типом проблемы, деталями, ссылкой на ИД задачи в Б24 и ее текущим статусом. Жизненный цикл alert: alert создается СС, обработка alert осуществляется в Б24 через смарт процесс "Конфликты синхронизации", БД регулярно опрашивает статус задач. После успешного разбора конфликта, СС корректирует статус в БД на "Завершено". ИД alerts нумеруются сиквенсом и передаются в Б24 при постановке задачи. Описанный механизм разбора конфликтов - используется для разбора бизнес-расхождений. Он не используется в случае технических сбоев или ошибок приложения.

3.3. Жизненный цикл пользователя приложения в контексте связи с контактом (на примере 1 пользователя): а) Клиент зарегистрировался по номеру телефона. СС запрашивает в Б24, есть ли клиенты с указанным номером телефона. Варианты: В0. 0 контактов. СС должен инициировать create, получить информацию об ИД нового пользователя, записать к себе ИД в Б24, в Б24 передать флаг привязки к Приложению. В1.1. 1 контакт + контакт не имеет связи с приложением. СС должен записать к себе ИД в Б24, в Б24 передать флаг привязки к Приложению. Если при этом в приложении флаг уже был, нам не важно. В1.2. 1 контакт + контакт уже привязан к другому активному пользователю приложения. СС должен инициировать create, получить информацию об ИД нового пользователя, записать к себе ИД в Б24, в Б24 передать флаг привязки к Приложению. Плюс СС создает alert об ошибке привязки. В2.1. 2 и более. СС выбирает самый новый контакт по creationtime. Выбранный контакт не имеет связи с приложением. СС должен записать к себе ИД в Б24, в Б24 передать флаг привязки к Приложению. Плюс СС создает alert наличии дублей контактов: необходимо проверить актуальность контактов, корректность закрепления. В2.2. 2 и более. СС выбирает самый новый контакт по creationtime. Выбранный контакт уже привязан к другому активному пользователю приложения. СС должен инициировать create, получить информацию об ИД нового пользователя, записать к себе ИД в Б24, в Б24 передать флаг привязки к Приложению. Плюс СС создает alert об ошибке привязки: с указанием деталей события (в том числе информация о наличии нескольких контактов).

б) Процесс обновления данных. Сейчас реализовываем только движение Б24 -> Приложение. Б24 отслеживает изменения данных контактов, у которых есть признак UF_CRM_6A70C275346A7 = 'Y' При изменении Б24 направляет вебхук СС СС при получении вебхука складывает в очередь задание на обновление данных соответствующего контакта. По расписанию выполняется запрос данных контактов из Б24. И обновляются сведения. Если в ответ на запрос по контакту не найдены данные, формируется alert (Пользователь приложения привязан к несуществующему контакту).

в) Клиент удалил профиль из приложения. Обновляем признак UF_CRM_6A70C275346A7 = 'N'. Деактивируем учетную запись.

Механизм изменения привязки ИД Битрикс24 к пользователю приложения - администратор вносит изменения напрямую в БД

4. Очередь и worker

4.1. Этот пункт - примерное видение. По нему можно смело предлагать улучшения, тк. получается несколько связанных асинхронных процессов.

В схеме han_app хранятся бизнесовые задачи на обновление данных. Должен быть воркер, который забирает эти задачи и стартует требуемые сценарии (map_or_create, update, delete, alert_create, alert_status_update).

Каждый сценарий предполагает набор действий и запросов в Б24. Обработчик сценария в рамках его исполнения формирует задачи на обмен данными с Б24 (один сценарий может предолагать несколько связанных задач). В следующем пункте расписал примерные запросы в Б24, которые могут возникать в ходе сценария. Тебе нужно более подробно сформулировать сценарий и действия.

Задачи на обмен с Б24 складываются в соответствующую таблицу в схеме sync. Обмен данными с Б24 осуществляется через механизм Батчей. Кроме операций синхронизации документов (не входят в текущую реализацию). Один вложенный в батч запрос должен относиться к одной задаче синхронизации. Отправка запроса осуществляется по шедулеру (по умолчанию каждые 5 секунд). Для этого отдельный воркер собирает задачи, находящиеся в статусе pending + кол-во tryes <max_retries (не более 20 штук в один батч). Задачи отбираются по принципу fifo. Если задач меньше 20, то батч формируется из меньшего числа задач. Если задач 0, то батч не формируется, запрос в битрикс не отправляется. Отобранные задачи переводятся в следующий статус (модель статусов предложи сам). После получения ответа успешные ответы переходят на следующий статус, неуспешные ответы, требующие retry, возвращаются в статус pending, кол-во tries + 1. Успешный ответ, касающийся задачи, сохраняем в таблице с задачами. Триггер (или шедулер) проверяет наличие задач в статусе pending + кол-во tries >=max_retries. Если находит, переводит в статус fail + отбрасывает бизнес-лог для разбора (в Битрикс24 задача не создается). Значения параметров прописываются в настройках сервиса в БД в схеме sync_service, изменения параметров в БД должны применяться сервисом без перезагрузки.

Какие у меня архитектурные сложности возникли, ограничивающие возможность полноценно поставить требования:

  1. Битрикс24 допускает до 5 api запросов в секунду. По идее при высокой нагрузке это может означать что регулярность шедулера можно настроить до 0,2 секунд. Я не понимаю, нужно ли тут какой-то параллелиризм вводить? или БД с одним шедулером справится, тк Б24 достаточно быстро отвечает. Но что произойдет, если Б24 за 0.2 секунды не ответит? Тут нужна твоя экспертиза и варианты.
  2. Как правильно организовать работу сценариев. Сценарий может содержать несколько последовательных действий, требующих обмена с Б24 и не требующих. Жизненный цикл отработки сценария начинается с момента, как я забрал задачу из han_app, или ее поставил сам СС. Держать в оперативной памяти сценарий на протяжении его жизненного цикла неправильно, тк очередь задач может забиться и либо все рухнет, либо сценарии перестанут запускаться - формируется точка отказа. Правильнее сценарий разделить на условно-атомарные операции, и раскладывать их в таблицу. И тогда какие-то воркеры могут быстро бегать по этой таблице, находить очередную операцию в рамках сценария, которая ждет исполнения, исполнять ее, переводить в статус "исполнена", чтобы активировать к возможности исполнения следующую задачу. Мне этот вариант кажется более отказоустойчивым и управляемым (плюс в любой момент, даже если грохнется сервис, можно запуститься с того места, где он грохнулся, и никакие сценарии не оборвутся). Но я не до конца понимаю, как тут управлять производительностью (можно ли много воркеров запускать, чтобы они параллельно работали, и в какой момент это нужно делать).

4.2. Виды запросов в Б24 с привязкой к сценариям: Сценарий регистрации пользователя: 1: поиск контакта по номеру телефона 2: создание нового контакта либо 3: обновление сведений контактов (изменений флага UF_CRM_6A70C275346A7)

Сценарий обновления 
4: запрос данных по контакту

Сценарий удаления профиля:
3: обновление сведений контактов (изменений флага UF_CRM_6A70C275346A7)

Сценарий обработки alerts:
5: поставить задачу в Б24
6: узнать статус задачи в Б24

... возможно еще понадобятся.
Используемые виды запросов хранятся в справочнике видов запросов и могут использоваться сервисом синхронизации в рамках запущенных процессов.

4.3. Сервис синхронизации должен ставить задачи на синхронизацию с использованием утвержденных видов запросов в Б24.

4.4. Готовы ли триггеры App DB и GRANT для bitrix_sync_user , или это часть той же постановки? Триггеры 'contact.map_or_create' и 'contact.update' при создании и изменении данных в таблицах пользователей готовы и работают. Действующие триггеры необходимо проверить, что они не будут пытаться синхронизировать изменения, полученные от битрикс24 и залитые в БД. Процессов постановки задач на обновление данных пользователя из-за вебхука от Б24, нет.

5. Bitrix24: доступ и webhook

5.1. Способ доступа к CRM REST: я верно понимаю, что local-app безопаснее входящего вебхука? Т.к невозможно, даже зная токен, отправить запрос в Б24? Если это так, то логично создать в Б24 еще одно локальное приложение и получать данные через него. Для вебхуков от Б24 делаем соответствующую ссылку с секретом. 5.2. Кто настраивает робота в Bitrix (какие события/поля). Сформируй требования к роботу и исходящему вебхуку, я настрою робот. 5.3. Есть ли тестовый портал отдельно от prod. Нет, портал один. При этом для разделения теста и прода будут использоваться различные local-app. Чтобы не смешивать базу, набор тестовых пользователей будет задаваться маской "нелегитимных" номеров.

6. Надёжность, безопасность, ops

6.1. Rate limit / квоты Bitrix REST: политика при QUERY_LIMIT_EXCEEDED? Кол-во попыток определено в п.4.1. Если не удалось - отбрасываем бизнес-логи. Правило универсально как для ошибок синхронизации, так и для QUERY_LIMIT_EXCEEDED. Можешь предложить вариант лучше, если есть идеи. 6.2. PII в логах/метриках: секреты в логах не допускаются. PII в логах маскируются: два первых читаемых и два последних читаемых символа поля отображаем как есть, остальные символы маскируем. Ошибки логируем как есть - т.к. сервис внутренний и недоступен пользователям. 6.3. Cutover: stub → full sync на уже накопленной очереди — replay всех pending или только новых? Управляем через .env: replay = true, значит replay всех pending. replay = false, значит все pending при раскатке сервиса переводим в статус "Cancelled".