Идемпотентная интеграция повторяет технический запрос без повторения его бизнес-результата. Если одна заявка доставлена трижды, должна появиться одна сделка, а все попытки должны ссылаться на неё. Для этого нужен устойчивый идентификатор операции и сохранённый результат; поиск совпадений по телефону сам по себе такую защиту не даёт.
Отделите заявку от человека
Один клиент может отправить два разных запроса. Телефон, почта и название компании помогают найти контакт, но не объясняют, относится ли сообщение к новой покупке. Поэтому идентификатор клиента и идентификатор события решают разные задачи.
Ключ операции желательно создавать там, где бизнес-событие возникает впервые. Например, сервер сайта присваивает принятый номер заявке и передаёт его при каждой повторной попытке. Если ключ строится из нескольких полей, зафиксируйте состав, нормализацию и область уникальности: источник, аккаунт, тип события, внешний номер.
Сохраните состояние обработки
Проектируемый журнал может содержать ключ, отпечаток полезных данных, состояние, время первой попытки, идентификатор созданной сделки и последнюю ошибку. Это отдельный элемент интеграции, а не обещание готового поля в любой CRM.
До внешнего вызова обработчик резервирует ключ. После подтверждения записи сохраняет результат. Повтор с тем же ключом и теми же данными возвращает этот результат. Повтор с изменённым содержимым требует понятного правила: обновление версии либо конфликт для разбора. Молчаливо принять оба варианта как одну операцию опасно.
Разберите неопределённый результат
Самый сложный случай — CRM выполнила создание, но ответ потерялся. Тайм-аут не доказывает, что сделки нет. Немедленный повтор создания может оставить две карточки.
Предусмотрите сверку по внешнему идентификатору операции, если выбранный API позволяет надёжно его хранить и искать. Когда такой возможности нет, разработчик должен объяснить альтернативный механизм и остаточный риск. Состояние «результат неизвестен» полезнее ложной отметки «ошибка, можно создать заново».
Условный пример с двумя обработчиками
Сайт принял заявку F-482, затем отправил её дважды из-за задержки ответа. Два обработчика одновременно видят новое сообщение. Если каждый сначала ищет запись, а затем создаёт её, оба могут успеть пройти проверку отсутствия.
Защита требует атомарного резервирования одного ключа в общем хранилище. Первый обработчик получает право выполнять операцию, второй видит занятый ключ и следует регламенту ожидания. После завершения оба сообщения связываются с одной сделкой. Просроченное резервирование нельзя просто удалить: прежде необходимо проверить, не произошла ли запись во внешней системе.
Установите границы хранения
Срок хранения ключей должен покрывать возможные повторы источника, ручную переотправку и восстановление из архивов. Если ключ забывается раньше повторной доставки, защита перестаёт работать именно во время инцидента.
Не храните в журнале больше клиентских данных, чем нужно для расследования. Обычно достаточно технического ключа, результата и ограниченного набора диагностических признаков. Доступ к журналу и его очистку согласуют как часть сопровождения, а не оставляют случайной настройкой сервера.
Проверьте защиту экспериментом
Подготовьте тестовую заявку и последовательно воспроизведите одинаковую доставку, конкурентную доставку, потерю ответа и перезапуск между внешней записью и сохранением результата. Затем отправьте другую заявку того же клиента: она должна обрабатываться как отдельное обращение.
Критерий приёмки состоит из трёх условий: одна операция даёт один результат, повтор можно объяснить по журналу, новая потребность клиента не теряется. Если база уже содержит дубли, сначала полезно определить их причины по руководству по очистке дублей amoCRM, а затем внедрять профилактику на входе.
Применить в вашей компании
Обсудим вашу задачу?
Поможем разобраться с процессом, данными и настройками. Работаем удалённо с компаниями по всей России.