При стандартной работе регламентных заданий, созданных на основе дополнительных обработок, система контролирует уникальность запуска фоновых заданий посредством поля УникальныйИдентификатор.
Но иногда происходит сбой штатного механизма и можно увидеть картину, когда всё новые и новые экземпляры фоновых заданий стартуют, не дожидаясь завершения предыдущих фоновых заданий по регламентному заданию. В некоторых случаях администратору приходится завершать такие задания:
Вторым недостатком является возможность запуска фонового задания пользователем вручную из справочника дополнительных обработок без проверки на уже запущенное фоновое задание.
Предлагаю решение в реализации проверки перед исполнением алгоритмов команд дополнительной обработки. Проверка заключается в поиске фоновых заданий по наименованию, которое генерируется типовым шаблоном при сохранении дополнительной обработки с расписанием. Проверка так же не должна учитывать текущее фоновое задание, т.е. которое запускается в первый раз.
В пример добавил свои методы реализации команд дополнительных обработок, процедуры ВыполнитьКоманду, в процессе разработки при таком подходе необходимо минимальное добавление/правка кода. Тестовым алгоритмом является типовая пауза.
Модуль формы (только для отладки, сама форма опциональна):
#Область ОбработчикиСобытийФормы
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
РеквизитФормыВЗначение("Объект").ВыполнитьКоманду("ПримерКомандыПоРасписанию");
КонецПроцедуры
#КонецОбласти
Модуль объекта:
#Область ПрограммныйИнтерфейс
Функция СведенияОВнешнейОбработке() Экспорт
ИмяОбработки = Метаданные().Имя;
Синоним = Метаданные().Синоним;
Синоним = ?(ЗначениеЗаполнено(Синоним), Синоним, ОбщегоНазначенияБПКлиентСервер.СинонимИзИмени(ИмяОбработки));
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке();
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
ПараметрыРегистрации.Наименование = Синоним;
ПараметрыРегистрации.Версия = "1.0";
ТаблицаКоманд = ПараметрыРегистрации.Команды;
Команда = ТаблицаКоманд.Добавить();
Команда.Идентификатор = "ПримерКомандыПоРасписанию";
Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
Команда.Представление = ОбщегоНазначенияБПКлиентСервер.СинонимИзИмени(Команда.Идентификатор);
Возврат ПараметрыРегистрации;
КонецФункции
Функция ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыКоманды = Неопределено) Экспорт
Если ЭтаКомандаВыполняется(ИдентификаторКоманды) Тогда
Возврат Неопределено;
КонецЕсли;
ОбщегоНазначения.ВыполнитьМетодОбъекта(ЭтотОбъект, ИдентификаторКоманды, ПараметрыКоманды);
КонецФункции
Процедура ПримерКомандыПоРасписанию() Экспорт
ИнтернетПоддержкаПользователей.Пауза(60);
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ЭтаКомандаВыполняется(ИдентификаторКоманды)
СведенияОВнешнейОбработке = СведенияОВнешнейОбработке();
Команда = СведенияОВнешнейОбработке.Команды.Найти(ИдентификаторКоманды, "Идентификатор");
НаименованиеФоновогоЗадания = ПредставлениеЗадания(Команда, СведенияОВнешнейОбработке);
ТекущееФоновоеЗадание = ПолучитьТекущийСеансИнформационнойБазы().ПолучитьФоновоеЗадание();
ОтборФоновыхЗаданий = Новый Структура;
ОтборФоновыхЗаданий.Вставить("Состояние", СостояниеФоновогоЗадания.Активно);
ОтборФоновыхЗаданий.Вставить("Наименование", НаименованиеФоновогоЗадания);
АктивныеФоновыеЗадания = ФоновыеЗадания.ПолучитьФоновыеЗадания(ОтборФоновыхЗаданий);
УдалитьТекущееФоновоеЗадание(АктивныеФоновыеЗадания, ТекущееФоновоеЗадание);
Возврат АктивныеФоновыеЗадания.Количество() > 0;
КонецФункции
Процедура УдалитьТекущееФоновоеЗадание(АктивныеФоновыеЗадания, ТекущееФоновоеЗадание)
Если ТекущееФоновоеЗадание = Неопределено Тогда
Возврат;
КонецЕсли;
КоличествоЭлементовКоллекции = АктивныеФоновыеЗадания.Количество();
Для ОбратныйИндекс = 1 По КоличествоЭлементовКоллекции Цикл
Индекс = КоличествоЭлементовКоллекции - ОбратныйИндекс;
Если АктивныеФоновыеЗадания[Индекс].УникальныйИдентификатор = ТекущееФоновоеЗадание.УникальныйИдентификатор Тогда
АктивныеФоновыеЗадания.Удалить(Индекс);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// '[ВидОбъекта]: [НаименованиеОбъекта] / Команда: [ПредставлениеКоманды]'
Функция ПредставлениеЗадания(Команда, СведенияОВнешнейОбработке)
Возврат (
СокрЛП(ДополнительныеОтчетыИОбработки.ПолучитьВидОбработкиПоСтроковомуПредставлениюВида(
СведенияОВнешнейОбработке.Вид))
+ ": "
+ СокрЛП(СведенияОВнешнейОбработке.Наименование)
+ " / "
+ НСтр("ru = 'Команда'")
+ ": "
+ СокрЛП(Команда.Представление));
КонецФункции
#КонецОбласти
Внедрялось и тестировалось на платформе 8.3.25.1374.
Вступайте в нашу телеграмм-группу Инфостарт