Проблема: скрипт «не видит» лиды, хотя они точно есть
Клиент обратился с конкретной жалобой: собственный PHP-скрипт, который должен выгружать лиды из Bitrix24 во внешнюю систему (1С/Excel), перестал это делать. В CRM лидов было достаточно, а на стороне выгрузки — пусто. Скрипт работал уже давно и раньше проблем не вызывал.
Первое желание в такой ситуации — открыть код и искать ошибку взглядом. Но беглый просмотр логики ничего не дал: код выглядел рабочим, никаких явных опечаток или сломанных условий. Значит, проблема была не в том, «что написано», а в том, как система на самом деле себя ведёт при реальной нагрузке.
Как искали причину: проверка API напрямую, в обход скрипта
Вместо того чтобы гадать по коду, мы начали обращаться к Bitrix24 напрямую — теми же запросами, что использует скрипт, но по одному, вживую, только на чтение, ничего не меняя в данных клиента.
Шаг 1. Проверили, сколько записей скрипт реально получает. Оказалось, что в списке для синхронизации — свыше 57 000 элементов, а Bitrix24 отдаёт максимум 50 штук за один запрос (это стандартное поведение API, а не ошибка). Скрипт брал именно эти первые 50 и не запрашивал следующую «страницу» результатов. Из нескольких сотен реально непроверенных лидов до обработки почти никогда не доходили те, что оказывались дальше пятидесятого места.
Шаг 2. Проверили, как скрипт забирает данные по найденным сделкам. Для этого он отправлял в Bitrix24 один «пакетный» запрос (batch) сразу на полсотни команд. Тестовый пакет из 50 команд подвисал больше минуты без ответа. Точно такой же пакет, но из 10 команд, отрабатывал за 1,4 секунды. Это и была вторая, более скрытая причина: Bitrix24 ограничивает не только объём одного списка, но и нагрузку одного запроса — и при превышении лимита начинает придерживать ответ, а не сразу возвращает ошибку, из-за чего создаётся впечатление, что «всё просто зависло».
Обе причины подтвердили не догадкой, а прямым замером на реальном аккаунте клиента — это заняло меньше времени, чем повторное чтение кода в поисках несуществующей опечатки.
В чём была реальная причина
Проблема была не в логике скрипта как таковой, а в двух неочевидных ограничениях самого API Bitrix24, с которыми скрипт изначально не был рассчитан работать:
- Список результатов приходит постранично, максимум по 50 записей — если не запрашивать следующие страницы явно, дальше первых 50 система «не видит».
- Пакетные запросы большого объёма (десятки команд разом) упираются в лимит на нагрузку и могут зависать без явной ошибки, а не просто выполняться медленнее.
Такие ограничения обычно не видны, пока данных мало — скрипт мог годами работать нормально, пока список синхронизации не разросся настолько, что стал упираться в эти лимиты.
Что сделали
Прежде чем что-либо менять на боевом сервере клиента, поправленную версию подняли на отдельном тестовом адресе с паролем — чтобы клиент сам, вживую, увидел разницу «до» и «после», а не действовал на веру.
- Добавили постраничную выгрузку. Скрипт теперь запрашивает все страницы результата по очереди, пока не заберёт все записи, а не только первую полсотню.
- Разбили пакетные запросы на порции. Вместо одного запроса на 50+ команд — несколько запросов по 10, выполняемых по очереди. Именно такой размер порции гарантированно укладывается в лимит и не подвисает.
- Добавили таймаут на каждый запрос. Если Bitrix24 всё же не ответит вовремя, скрипт теперь явно сообщит об ошибке, а не будет молча висеть — это отдельная страховка на случай похожей ситуации в будущем.
Что это значит для вашего бизнеса
Если у вас есть собственная интеграция с Bitrix24, amoCRM или другой CRM-системой — особенно написанная давно или под небольшой объём данных — стоит иметь в виду: подобные скрипты часто не ломаются в привычном смысле, а просто перестают справляться с выросшим объёмом данных, упираясь в лимиты API. Внешне это выглядит как случайный сбой, а не как закономерность, поэтому его сложно поймать без прямой проверки поведения самого API.
Часто задаваемые вопросы
Можно ли было найти эту проблему просто читая код?
Маловероятно: код был написан корректно с точки зрения синтаксиса и логики, а проблема проявлялась только в поведении внешнего API при определённом объёме данных — такое видно только при живом тестировании.
Значит ли это, что у нас тоже может быть такая проблема?
Если интеграция с CRM работает через пакетные запросы или списки без явной постраничной обработки — риск есть, особенно если объём данных со временем вырос. Стоит заранее проверить, как скрипт ведёт себя при большом количестве записей.
Почему исправление тестировали отдельно, а не сразу на боевом сервере?
Скрипт работает с реальными данными клиента в CRM — часть действий необратима (например, удаление элементов). Тестовый адрес с паролем позволил показать клиенту рабочее поведение без риска для боевых данных.
Читайте также: