При интеграции 1С с внешними веб-сервисами и REST API разработчики часто сталкиваются с жесткими лимитами на частоту обращений (Rate Limiting). Например, сервис может разрешать отправку не более одного запроса в несколько секунд. В таких ситуациях возникает необходимость принудительно приостановить выполнение программного кода на определенный интервал времени перед отправкой следующего пакета данных.
В платформе 1С:Предприятие нет универсальной встроенной функции Сон() или Sleep(), однако существует несколько способов реализовать задержку как на стороне клиента, так и на стороне сервера. Разберем основные варианты реализации, их плюсы, минусы и особенности применения.
Самый простой и быстрый способ организовать задержку прямо внутри алгоритма или цикла обработки данных — использовать цикл ожидания по системному времени.
Посмотрим на пример реализации паузы длительностью 3 секунды:
Старт = ТекущаяДата();
Пока ТекущаяДата() - Старт < 3 Цикл
// Пустой цикл ожидания
КонецЦикла;
Разберем, как применить этот подход при циклическом обращении к внешнему сервису:
Для Каждого Стр Из ТаблицаОтправок Цикл
// Выполняем обращение к сервису
РезультатЗапросаHTTP = Соединение.Получить(ОбъектHTTPЗапрос);
// Обрабатываем ответ
ОбработатьОтвет(РезультатЗапросаHTTP);
// Делаем задержку перед следующим запросом к API
Старт = ТекущаяДата();
Пока ТекущаяДата() - Старт < 3 Цикл
// Ожидание завершения 3 секунд
КонецЦикла;
КонецЦикла;
Проанализируем особенности и недостатки данного метода:
ТекущаяДата() возвращает время с точностью до секунды, поэтому фактическая длительность задержки может колебаться в диапазоне от 2,001 до 3,999 секунд.Этот способ допустим только для редких разовых операций с небольшим числом итераций, когда нет возможности задействовать асинхронные методы платформы.
Для клиентского контекста управляемых и обычных форм правильным архитектурным решением является использование процедуры ПодключитьОбработчикОжидания(). Это позволяет разделить выполнение длительного процесса на порции без блокировки пользовательского интерфейса.
Разберем по шагам, как настроить периодический вызов процедуры:
&НаКлиенте
Процедура ЗапуститьОбработку()
// Подключаем однократный вызов процедуры через 3 секунды
ПодключитьОбработчикОжидания("ВыполнитьШагОбработки", 3, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьШагОбработки()
// Выполняем один шаг запроса к API
ВыполнитьЗапросКСервису();
// Если остались необработанные данные, планируем следующий вызов
Если ЕстьДанныеДляОбработки() Тогда
ПодключитьОбработчикОжидания("ВыполнитьШагОбработки", 3, Истина);
Иначе
ПоказатьОповещениеПользователю("Обработка завершена");
КонецЕсли;
КонецПроцедуры
Особенности метода:
ПодключитьОбработчикОжидания() доступен только на клиенте и не может быть вызван в серверном модуле или в фоновом задании.Для серверного кода в конфигурациях на платформе 1С:Предприятие 8.3 можно использовать механизм ожидания завершения фоновых заданий. Метод ФоновыеЗадания.ОжидатьЗавершения() принимает массив заданий и таймаут ожидания в секундах, переводя текущий поток сервера в режим сна без загрузки процессора.
Посмотрим на пример реализации универсальной функции паузы:
&НаСервере
Процедура СделатьПаузу(ВремяВСекундах)
ПустойМассивЗаданий = Новый Массив;
Попытка
// Метод приостанавливает поток на указанное время
ФоновыеЗадания.ОжидатьЗавершения(ПустойМассивЗаданий, ВремяВСекундах);
Исключение
// Перехват возможного исключения по истечении таймаута
КонецПопытки;
КонецПроцедуры
Преимущества этого способа:
Еще один способ организации паузы без загрузки процессора — синхронный запуск консольной команды операционной системы с параметром ожидания завершения.
Рассмотрим пример кода для операционных систем Windows и Linux:
&НаСервереИлиНаКлиенте
Процедура ПаузаОС(Секунды)
// Для Windows используем утилиту timeout или ping
Команда = "timeout /t " + Формат(Секунды, "ЧГ=0") + " /nobreak";
// Для Linux можно использовать: Команда = "sleep " + Формат(Секунды, "ЧГ=0");
ЗапуститьПриложение(Команда, , Истина);
КонецПроцедуры
При использовании этого метода важно учитывать операционную систему, на которой развернут сервер 1С, а также права учетной записи службы сервера на запуск внешних процессов.
При циклической отправке запросов к внешним сервисам обратим внимание на типичные ошибки и рекомендации по их устранению:
HTTPСоединение: Не создавайте экземпляр Новый HTTPСоединение внутри каждой итерации цикла. Инициализируйте соединение один раз перед началом цикла, а внутри цикла создавайте только объекты HTTPЗапрос. Это избавит систему от повторных процедур установки TCP-соединения и TLS-рукопожатия.HTTPСоединение передавайте только доменное имя сервера (например, "api.laposte.fr"), а путь к конкретному ресурсу (например, "/suivi/v1/track") указывайте в конструкторе HTTPЗапрос.КодСостояния ответа. Если сервис возвращает код 429, значит лимит запросов был превышен. В этом случае следует прочитать заголовок ответа Retry-After, выполнить паузу на указанное сервером время и повторить отправку запроса.