У меня есть регламентное задание, которое выполняет функцию каждые 15 минут. Также функцию может вызвать вручную пользователь. Если функция уже выполняется, то пользователь, запустив ее вручную, рискует получить ошибки в данных.
Чтобы контролировать процесс, первое, что приходит в голову - записывать время старта и время окончания и проверять, выполняется ли функция. Но тут есть вопросы, связанные с обработкой ошибок, выключением сервера или даже падением сессии регламентных заданий.
Придется писать проверки, которые смотрят за статистикой выполнения и если интервал превышен, то...
Но есть способ гораздо проще. Это стандартные блокировки объектов 1С. Для этого у меня есть справочник:
Поле ТипОбъектаКонтроля - это перечисление в котором находятся все разделы функционала вызываемые регламентными заданиями. Стандартная функция, которая осуществляет блокировку:
ОбъектСправочника.Заблокировать();
Если мы в функции, которая выполняется будем проверять блокировку и блокировать элемент справочника. То даже если сессия упадет, или закончится ошибкой, у нас не возникнет ситуации "вечной блокировки".
Немного кода. Очень важно вернуть в вашу функцию объект блокировки. Если этого не сделать, блокировка снимется автоматически.
&НаСервере
Функция ЗаблокироватьПоТипуОбъектаКонтроля(_ТипОбъектаКонтроля, _Комментарий = "") Экспорт
Результат = Неопределено;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| БлокировкиФункционала.Ссылка
|ИЗ
| Справочник.БлокировкиФункционала КАК БлокировкиФункционала
|ГДЕ
| БлокировкиФункционала.ПометкаУдаления = ЛОЖЬ
| И БлокировкиФункционала.ТипОбъектаКонтроля = &ТипОбъектаКонтроля";
Запрос.УстановитьПараметр("ТипОбъектаКонтроля", _ТипОбъектаКонтроля);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Если Не ВыборкаДетальныеЗаписи.Количество() = 1 Тогда
Возврат Результат;
КонецЕсли;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
БФ = ВыборкаДетальныеЗаписи.Ссылка;
БФО = БФ.ПолучитьОбъект();
Попытка
БФО.Заблокировать();
БФО.ДатаБлокировки = ТекущаяДата();
БФО.Комментарий = _Комментарий;
БФО.Записать();
Исключение
Результат = Неопределено;
КонецПопытки;
Результат = БФО;
КонецЦикла;
Возврат Результат;
КонецФункции
&НаСервере
Функция РазблокироватьПоТипуОбъектаКонтроля(_ТипОбъектаКонтроля, _Комментарий = "") Экспорт
Результат = Неопределено;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| БлокировкиФункционала.Ссылка
|ИЗ
| Справочник.БлокировкиФункционала КАК БлокировкиФункционала
|ГДЕ
| БлокировкиФункционала.ПометкаУдаления = ЛОЖЬ
| И БлокировкиФункционала.ТипОбъектаКонтроля = &ТипОбъектаКонтроля";
Запрос.УстановитьПараметр("ТипОбъектаКонтроля", _ТипОбъектаКонтроля);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Если Не ВыборкаДетальныеЗаписи.Количество() = 1 Тогда
Возврат Результат;
КонецЕсли;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
БФ = ВыборкаДетальныеЗаписи.Ссылка;
БФО = БФ.ПолучитьОбъект();
Попытка
БФО.ДатаБлокировки = ОбщийСерверКеш.ПустаяДата();
БФО.Комментарий = "";
БФО.Записать();
БФО.Разблокировать();
Исключение
Результат = Неопределено;
КонецПопытки;
Результат = БФО;
КонецЦикла;
Возврат Результат;
КонецФункции
&НаСервере
Функция ПроверитьБлокировкуПоТипуОбъектаКонтроля(_ТипОбъектаКонтроля) Экспорт
Результат = Ложь;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| БлокировкиФункционала.Ссылка
|ИЗ
| Справочник.БлокировкиФункционала КАК БлокировкиФункционала
|ГДЕ
| БлокировкиФункционала.ПометкаУдаления = ЛОЖЬ
| И БлокировкиФункционала.ТипОбъектаКонтроля = &ТипОбъектаКонтроля";
Запрос.УстановитьПараметр("ТипОбъектаКонтроля", _ТипОбъектаКонтроля);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Если Не ВыборкаДетальныеЗаписи.Количество() = 1 Тогда
Возврат Результат;
КонецЕсли;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
БФ = ВыборкаДетальныеЗаписи.Ссылка;
БФО = БФ.ПолучитьОбъект();
Попытка
БФО.Заблокировать();
Исключение
Результат = Истина;
КонецПопытки;
КонецЦикла;
Возврат Результат;
КонецФункции