Нововведение в платформе 1С 8.3.27: задание расписания перезапуска процессов
В версии платформы 1С:Предприятие 8.3.27 изменился подход к настройке расписания перезапуска рабочих процессов.
Ранее задавалось количество секунд, по истечении которых выполнялся перезапуск. Такой способ был не всегда удобен — процессы могли перезапускаться в произвольное время, в том числе в часы пиковой нагрузки.
Теперь, начиная с версии 8.3.27, расписание задаётся в формате cron, что позволяет гибко контролировать время перезапуска и исключить нежелательные простои.
Подробнее об изменениях можно прочитать здесь:
Для удобства можно использовать специальную обработку, которая помогает сформировать расписание в нужном формате с помощью визуального конструктора и сгенерировать даты запуска на основе заданных параметров.
Код для парсинга cron строки и получения дат запуска, работает быстро (от 3 до 50 мил.сек.):
// ТекстРасписания - Строка в формате cron
// ДатаНачалаРасчета - Дата начала с которой начнется расчет
// МаксимальноеКоличество - Максимальное количество возвращаемых дат
// Возврат - Массив - Даты следующих запусков
Функция ПолучитьБлижайшиеДатыРасписания(знач ТекстРасписания,ДатаНачалаРасчета,МаксимальноеКоличество) Экспорт
// Приводим cron-текст в единообразный вид: удаляем табуляции и переводы строк
ТекстРасписания = СтрЗаменить(ТекстРасписания,Символы.Таб," ");
ТекстРасписания = СтрЗаменить(ТекстРасписания,Символы.ПС,"");
// Убираем лишние пробелы подряд
Пока СтрНайти(ТекстРасписания," ") > 1 Цикл
ТекстРасписания = СтрЗаменить(ТекстРасписания," "," ");
КонецЦикла;
// Расписаний может быть несколько, разделенных точкой с запятой
пМассивРасписаний = СтрРазделить(ТекстРасписания,";");
пНайденныеЗначения = Новый Соответствие; // Здесь будут храниться все найденные даты выполнения
Отказ = Ложь;
// Обрабатываем каждое расписание отдельно
Для Каждого ТекРасписание Из пМассивРасписаний Цикл
ОбработатьКонкретноеРасписание(СокрЛП(ТекРасписание),пНайденныеЗначения,ДатаНачалаРасчета,МаксимальноеКоличество,Отказ);
Если Отказ Тогда
прервать;
КонецЕсли;
КонецЦикла;
// Если ошибок не было — пишем, что всё успешно
Если не Отказ Тогда
Комментарий = "Все ок!";
КонецЕсли;
// Преобразуем найденные значения в список и сортируем
СЗ = Новый СписокЗначений;
Для Каждого Тек Из пНайденныеЗначения Цикл
СЗ.Добавить(Тек.Ключ);
КонецЦикла;
СЗ.СортироватьПоЗначению();
// Возвращаем массив найденных дат
Возврат СЗ.ВыгрузитьЗначения();
КонецФункции
Процедура ОбработатьКонкретноеРасписание(ТекРасписаниеТекст,пНайденныеЗначения,ДатаНачалаРасчета,МаксимальноеКоличество,Отказ)
// Разбиваем cron-запись по пробелам
пМассивЗначений = СтрРазделить(ТекРасписаниеТекст," ",Ложь);
пКоличествоЗначений = пМассивЗначений.Количество();
// Проверяем количество частей cron-строки (должно быть 5 или 6)
Если пКоличествоЗначений < 5 Или пКоличествоЗначений > 6 Тогда
Комментарий = "В расписании: " + ТекРасписаниеТекст + " обнаружено некорректное количество значений: " + Строка(пКоличествоЗначений);
Отказ = Истина;
Возврат;
КонецЕсли;
// Получаем возможные значения минут, часов, дней, месяцев и дней недели
пМассивМинут = ПолучитьМассивЗначений(пМассивЗначений[0],0,59,Отказ,Истина);
пМассивЧас = ПолучитьМассивЗначений(пМассивЗначений[1],0,23,Отказ,Истина);
пМассивДень = ПолучитьМассивЗначений(пМассивЗначений[2],1,31,Отказ);
пМассивМесяц = ПолучитьМассивЗначений(пМассивЗначений[3],1,12,Отказ);
пМассивДеньНедели = ПолучитьМассивЗначений(пМассивЗначений[4],0,6,Отказ);
// Инициализация параметров поиска
пДеньНачала = НачалоДня(ДатаНачалаРасчета);
пКоличествоНайденных = 0;
пСекундВСутках = 60*60*24;
пМаксимальнаяГлубинаПоиска = 365*3; // ограничение на 3 года вперёд
// Перебор дней для поиска совпадений с расписанием
Для сч = 0 по пМаксимальнаяГлубинаПоиска Цикл
пТекДень = пДеньНачала + (пСекундВСутках*сч);
// Получаем совпадения по текущему дню
пМассивНайденных = ПолучитьМассивСовпадений(пТекДень,пМассивМинут,пМассивЧас,пМассивДень,пМассивМесяц,пМассивДеньНедели);
Для Каждого ТекНайденное Из пМассивНайденных Цикл
// Добавляем дату, если она не раньше даты начала расчета
Если ТекНайденное >= ДатаНачалаРасчета Тогда
пНайденныеЗначения.Вставить(ТекНайденное,Истина);
пКоличествоНайденных = пКоличествоНайденных + 1;
КонецЕсли;
КонецЦикла;
// Прерываем поиск, если достигнуто нужное количество дат
Если пКоличествоНайденных >= МаксимальноеКоличество Тогда
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ПолучитьМассивСовпадений(пТекДень,пМассивМинут,пМассивЧас,пМассивДень,пМассивМесяц,пМассивДеньНедели)
пМасСовпадений = Новый массив;
// Проверяем, соответствует ли день недели расписанию
пТекДеньНедели = ДеньНедели(пТекДень);
Если Не СовпалоЗначение(пМассивДеньНедели,7,?(пТекДеньНедели=7,0,пТекДеньНедели)) Тогда
Возврат пМасСовпадений;
КонецЕсли;
// Проверяем месяц
Если Не СовпалоЗначение(пМассивМесяц,12,Месяц(пТекДень)) Тогда
Возврат пМасСовпадений;
КонецЕсли;
// Проверяем день месяца
Если Не СовпалоЗначение(пМассивДень,31,День(пТекДень)) Тогда
Возврат пМасСовпадений;
КонецЕсли;
// Если день подходит — формируем список дат с учётом часов и минут
Для Каждого ТекЧас ИЗ пМассивЧас Цикл
Для Каждого ТекМин Из пМассивМинут Цикл
пМасСовпадений.Добавить(пТекДень + ТекЧас * 3600 + ТекМин *60);
КонецЦикла;
КонецЦикла;
Возврат пМасСовпадений;
КонецФункции
Функция СовпалоЗначение(пМассивЗначений,МаксимальноеКоличество,ТекщееЧисло)
// Если массив содержит все возможные значения (например, "*"), то всегда совпадает
пКолВо = пМассивЗначений.Количество();
Если пКолВо = МаксимальноеКоличество Тогда
Возврат Истина;
КонецЕсли;
// Проверяем, содержится ли текущее число в массиве значений
пСовпало = Ложь;
Для Каждого ТекЗН Из пМассивЗначений Цикл
Если ТекЗН = ТекщееЧисло Тогда
пСовпало = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат пСовпало;
КонецФункции
Функция ПолучитьМассивЗначений(пТекст,Минзнч,МаксЗнч,Отказ,ПрибавитьЕдиницу = Ложь)
пСоотв = Новый Соответствие;
// Разбиваем строку значений по запятым (например, "1,15,30")
пМассивЗначений = СтрРазделить(пТекст,",",Ложь);
Для Каждого ТекЗнч Из пМассивЗначений Цикл
Попытка
Если ТекЗнч = "*" Тогда // Все возможные значения
Для сч = Минзнч по МаксЗнч Цикл
пСоотв.Вставить(сч,Истина);
КонецЦикла;
Иначе
// Проверяем, содержит ли выражение шаг "/" или диапазон "-"
пЕстьКаждые = СтрНайти(ТекЗнч,"/") > 0;
пЕстьИнтервал = СтрНайти(ТекЗнч,"-") > 0;
Если пЕстьКаждые Тогда
// Обрабатываем выражения вроде */5 (каждые 5 минут)
пМас = СтрРазделить(ТекЗнч,"/",Ложь);
пНачатьС = ?(пМас[0]="*",МинЗнч,Макс(Минзнч,Число(пМас[0])));
пЗначенияТекст = пМас[1];
Иначе
пНачатьС = МинЗнч;
пЗначенияТекст = ТекЗнч;
КонецЕсли;
пМассивТекущихЗначений = Новый Массив;
Если пЕстьИнтервал Тогда
// Обрабатываем диапазон, например "10-20"
пМасИнтервалов = СтрРазделить(пЗначенияТекст,"-",ложь);
Для счЗначений = Число(пМасИнтервалов[0]) по Число(пМасИнтервалов[1]) Цикл
пМассивТекущихЗначений.Добавить(счЗначений);
КонецЦикла;
Иначе
// Простое число без диапазона
пМассивТекущихЗначений.Добавить(Число(пЗначенияТекст));
КонецЕсли;
Если пЕстьКаждые Тогда
// Формируем список значений для выражений "*/n" или "x/n"
Для Каждого сч_Период Из пМассивТекущихЗначений Цикл
пТекНомерПериода = 1;
Для сч_Число = Минзнч по МаксЗнч Цикл
Если сч_Период = пТекНомерПериода Тогда
Если сч_Число >= пНачатьС Тогда
сч_Число_нов = ?(ПрибавитьЕдиницу,?(сч_Число + 1 = МаксЗнч,0,сч_Число + 1),сч_Число);
пСоотв.Вставить(сч_Число_нов,Истина);
КонецЕсли;
пТекНомерПериода = 0;
КонецЕсли;
пТекНомерПериода = пТекНомерПериода + 1;
КонецЦикла;
КонецЦикла;
Иначе
// Добавляем конкретные значения в пределах диапазона
Для Каждого сч_Число Из пМассивТекущихЗначений Цикл
Если сч_Число >= Минзнч и сч_Число <= МаксЗнч Тогда
пСоотв.Вставить(сч_Число,Истина);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
Исключение;
// При ошибке парсинга фиксируем текст ошибки и выходим
Комментарий = Строка(ОписаниеОшибки());
Отказ = Истина;
Возврат новый Массив;
Конецпопытки;
КонецЦикла;
// Преобразуем найденные значения в список и сортируем
СЗ = Новый СписокЗначений;
Для Каждого Тек Из пСоотв Цикл
СЗ.Добавить(Тек.Ключ);
КонецЦикла;
СЗ.СортироватьПоЗначению();
Возврат СЗ.ВыгрузитьЗначения();
КонецФункции
Проверено на следующих конфигурациях и релизах:
- 1С:Библиотека стандартных подсистем, редакция 3.1, релизы 3.1.11.299
Вступайте в нашу телеграмм-группу Инфостарт