При разработке подписок на события часто возникает архитектурная ошибка: интеграционные и сетевые действия (отправка писем по протоколу SMTP, вызовы HTTP-сервисов, обращение к внешним API) выполняются непосредственно в обработчике события ПриЗаписи. Разберем, почему синхронная отправка писем замедляет работу пользователей, какие риски она несет для базы данных и как реализовать надежную асинхронную схему обработки.
Проанализируем механику работы платформы 1С:Предприятие при записи ссылочного объекта. Обработчик подписки на событие ПриЗаписи выполняется строго внутри транзакции записи базы данных. Это порождает сразу несколько критических проблем:
ИнтернетПочтовыйПрофиль по умолчанию использует таймаут подключения до 30–60 секунд. Если SMTP-сервер недоступен, происходят потери пакетов или возникают проблемы с DNS, пользовательский сеанс зависает на все время ожидания сетевого ответа.Рассмотрим классический и наиболее надежный способ разделения транзакционной логики и сетевых вызовов — создание очереди исходящих сообщений с отложенной обработкой регламентным или фоновым заданием.
Разберем по шагам, как устроен этот механизм:
ОчередьИсходящихПисем с измерениями Идентификатор (тип УникальныйИдентификатор), ресурсами Тема, АдресПолучателя, ТекстПисьма, ДатаСоздания и реквизитом КоличествоПопыток.ПриЗаписи формируем текст и параметры письма, но не выполняем сетевой отправки, а быстро фиксируем запись в регистре сведений. Запись в регистр происходит за доли миллисекунды в той же транзакции.Посмотрим на пример заполнения очереди в обработчике события:
Процедура КонтрагентыПриЗаписи(Источник, Отказ) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Формируем запись в регистр очереди
МенеджерЗаписи = РегистрыСведений.ОчередьИсходящихПисем.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Идентификатор = Новый УникальныйИдентификатор();
МенеджерЗаписи.АдресПолучателя = "control@example.com";
МенеджерЗаписи.Тема = "Изменен контрагент: " + СокрЛП(Источник.Наименование);
МенеджерЗаписи.ТекстПисьма = "Пользователь обновил данные контрагента " + Источник.Наименование;
МенеджерЗаписи.ДатаСоздания = ТекущаяДатаСеанса();
МенеджерЗаписи.Записать();
КонецПроцедуры
Если конфигурация разработана на основе БСП, писать кастомные регистры и механизмы не требуется. Рассмотрим встроенные средства, решающие задачу «из коробки»:
ИнтернетПочта создается документ ЭлектронноеПисьмоИсходящее в статусе «Черновик» или «К отправке». Встроенное регламентное задание ОтправкаПолучениеПочты автоматически отправляет накопленные письма в фоновом режиме, ведет логирование попыток и фиксирует дату фактической отправки.Если уведомление должно уйти не по расписанию регламентного задания раз в минуту, а сразу же, можно запустить фоновый поток платформы. Вызов фонового задания выполняется вне транзакции (например, в обработчике формы ПослеЗаписиНаСервере или через вызов процедуры общего модуля):
ПараметрыПроцедуры = Новый Структура;
ПараметрыПроцедуры.Вставить("КонтрагентСсылка", КонтрагентОбъект.Ссылка);
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(ПараметрыПроцедуры);
ФоновыеЗадания.Выполнить("ИнтеграцияПочта.ОтправитьУведомлениеФон", ПараметрыЗадания);
При таком подходе транзакция завершается мгновенно, форма контрагента закрывается без задержек, а сетевой стек 1С взаимодействует с почтовым сервером в изолированном фоновом сеансе.
Проанализируем системные причины медленного SMTP-соединения. Если подключение к почтовому серверу занимает более 1–2 секунд, необходимо проверить следующие факторы:
hosts решает проблему.127.0.0.1 без использования внешнего интернета, а релей самостоятельно организует повторные попытки доставки при сбоях внешнего канала.