11. Расписания и фоновые задачи
11.1. Общая концепция
Платформа поддерживает два типа фонового выполнения:
| Тип | Ключевое слово | Назначение | Запуск |
|---|---|---|---|
| Периодические задачи | РАСПИСАНИЕ |
Выполнение по расписанию (CRON) | Автоматически при старте платформы |
| Разовые фоновые задачи | ВЫПОЛНИТЬ_ФОНОВО |
Асинхронный вызов процедуры | Из любой процедуры или логики |
Особенности:
- Фоновые задачи выполняются параллельно с основным потоком
- Не блокируют интерфейс пользователя
- Результаты работы видны только через
ВЫВЕСТИ(логи) или изменения в БД
11.2. Расписания (периодические задачи)
Синтаксис:
РАСПИСАНИЕ ИмяРасписания
КРОН "секунды минуты часы дни месяцы дни_недели"
ВЫЗВАТЬ Процедура.ИмяПроцедуры
КОНЕЦ_РАСПИСАНИЯ
Формат CRON (6 полей):
┌───────────── секунды (0-59)
│ ┌───────────── минуты (0-59)
│ │ ┌───────────── часы (0-23)
│ │ │ ┌───────────── дни месяца (1-31)
│ │ │ │ ┌───────────── месяцы (1-12)
│ │ │ │ │ ┌───────────── дни недели (0-6, 0 = воскресенье)
│ │ │ │ │ │
* * * * * *
Специальные символы:
| Символ | Значение | Пример |
|---|---|---|
* | уетсяВсе значения* * * * * * — каждую секунду |
|
*/N |
Каждые N единиц | */5 * * * * * — каждые 5 секунд |
N |
Конкретное значение | 0 0 9 * * * — в 9:00 каждый день |
N-M |
Диапазон | 0 0 9-17 * * * — каждый час с 9 до 17 |
N,M |
Несколько значений | 0 0 9,12,15 * * * — в 9, 12 и 15 часов |
Примеры расписаний:
# Каждые 10 секунд
РАСПИСАНИЕ ПроверкаНовыхЗаказов
КРОН "*/10 * * * * *"
ВЫЗВАТЬ Процедура.Заказы.ПроверитьНовые
КОНЕЦ_РАСПИСАНИЯ
# Каждую минуту
РАСПИСАНИЕ ОбновлениеСтатусов
КРОН "0 * * * * *"
ВЫЗВАТЬ Процедура.Статусы.ОбновитьПросроченные
КОНЕЦ_РАСПИСАНИЯ
# Каждый час
РАСПИСАНИЕ ЧасовойОтчет
КРОН "0 0 * * * *"
ВЫЗВАТЬ Процедура.Отчеты.СформироватьЧасовойОтчет
КОНЕЦ_РАСПИСАНИЯ
# Каждый день в 2 часа ночи
РАСПИСАНИЕ НочнаяОчистка
КРОН "0 0 2 * * *"
ВЫЗВАТЬ Процедура.Очистка.УдалитьСтарыеЛоги
КОНЕЦ_РАСПИСАНИЯ
# Каждый понедельник в 9:00
РАСПИСАНИЕ ПонедельничныйОтчет
КРОН "0 0 9 * * 1"
ВЫЗВАТЬ Процедура.Отчеты.НедельныйОтчет
КОНЕЦ_РАСПИСАНИЯ
# В рабочие дни (пн-пт) в 18:30
РАСПИСАНИЕ ВечерняяСверка
КРОН "0 30 18 * * 1-5"
ВЫЗВАТЬ Процедура.Сверка.СверитьОстатки
КОНЕЦ_РАСПИСАНИЯ
11.3. Фоновый вызов процедур
Синтаксис:
ВЫПОЛНИТЬ_ФОНОВО Процедура.ИмяПроцедуры
ВЫПОЛНИТЬ_ФОНОВО Процедура.ИмяПроцедуры(аргумент1, аргумент2)
Примеры вызова:
# Без аргументов
ПРИ СОХРАНЕНИИ
ВЫПОЛНИТЬ_ФОНОВО Процедура.ОтправитьУведомление
КОНЕЦ
# С аргументами
ПРИ ПРОВЕДЕНИИ
ВЫПОЛНИТЬ_ФОНОВО Процедура.СоздатьПлатежку(data.id, data.Сумма)
КОНЕЦ
11.4. Полные примеры
Пример 1: Автоматическое создание задач
ПРОЦЕДУРА Задачи.СоздатьАвтоматическуюЗадачу
ВЫВЕСТИ "Планировщик: создаю новую задачу"
ВЫЧИСЛИТЬ НоваяЗадача = СОЗДАТЬ("Задачи")
ЗАПОЛНИТЬ НоваяЗадача.Наименование = "Автоматическая задача от КРОНа"
ЗАПОЛНИТЬ НоваяЗадача.Статус = "Новая"
ВЫЧИСЛИТЬ Успех = ЗАПИСАТЬ(НоваяЗадача)
ЕСЛИ Успех ТО
ВЫВЕСТИ "Создана задача ID: " + НоваяЗадача.id
КОНЕЦ
КОНЕЦ_ПРОЦЕДУРЫ
РАСПИСАНИЕ ГенераторЗадач
КРОН "*/30 * * * * *"
ВЫЗВАТЬ Процедура.Задачи.СоздатьАвтоматическуюЗадачу
КОНЕЦ_РАСПИСАНИЯ
Пример 2: Отправка уведомлений в фоне
ПРОЦЕДУРА Уведомления.ОтправитьОПроведенииЗаказа(ЗаказID)
ВЫЧИСЛИТЬ Заказ = ПРОЧИТАТЬ("ЗаказНаряд", ЗаказID)
ВЫЧИСЛИТЬ Клиент = ПРОЧИТАТЬ("Клиенты", Заказ.Клиент)
ПОПЫТКА
ВЫЧИСЛИТЬ Ответ = HTTP_ЗАПРОС("POST", "https://email-service.com/send", {
"to": Клиент.Email,
"subject": "Ваш заказ проведён",
"body": "Заказ №" + Заказ.Номер + " проведён"
})
ВЫВЕСТИ "Уведомление отправлено"
ИСКЛЮЧЕНИЕ Ошибка
ВЫВЕСТИ "Ошибка: " + Ошибка
КОНЕЦ_ПОПЫТКИ
КОНЕЦ_ПРОЦЕДУРЫ
ДОКУМЕНТ ЗаказНаряд
ЛОГИКА
ПРИ ПРОВЕДЕНИИ
ВЫПОЛНИТЬ_ФОНОВО Процедура.Уведомления.ОтправитьОПроведенииЗаказа(data.id)
КОНЕЦ
КОНЕЦ
КОНЕЦ
Пример 3: Автоматическое закрытие просроченных заказов
ПРОЦЕДУРА Заказы.ЗакрытьПросроченные
ВЫВЕСТИ "Проверка просроченных заказов"
ВЫЧИСЛИТЬ Просроченные = НАЙТИ_ВСЕ("ЗаказНаряд",
"Статус = 'В работе' AND Дата < date('now', '-14 days')")
ВЫЧИСЛИТЬ Закрыто = 0
ЦИКЛ ПО Просроченные КАК Заказ
ЗАПОЛНИТЬ Заказ.Статус = "Автоматически закрыт"
ВЫЧИСЛИТЬ _ = ЗАПИСАТЬ(Заказ)
ВЫЧИСЛИТЬ Закрыто = Закрыто + 1
КОНЕЦ_ЦИКЛА
ВЫВЕСТИ "Закрыто заказов: " + Закрыто
КОНЕЦ_ПРОЦЕДУРЫ
РАСПИСАНИЕ Заказы.НочнаяПроверка
КРОН "0 0 1 * * *"
ВЫЗВАТЬ Процедура.Заказы.ЗакрытьПросроченные
КОНЕЦ_РАСПИСАНИЯ
11.5. Важные особенности
1. Фоновые задачи не возвращают результат
# Нельзя получить возврат из фоновой задачи
ВЫЧИСЛИТЬ Результат = ВЫПОЛНИТЬ_ФОНОВО Процедура.Чтото() # ОШИБКА!
2. Передача аргументов в фоновую задачу
# Передаём примитивные типы
ВЫПОЛНИТЬ_ФОНОВО Процедура.Обработать(ID, "строка", 123)
# В процедуре-получателе
ПРОЦЕДУРА Обработать(ID, Строка, Число)
ВЫВЕСТИ "Получено: " + ID + ", " + Строка
КОНЕЦ_ПРОЦЕДУРЫ
3. Логирование в фоновых задачах
Весь вывод ВЫВЕСТИ из фоновых задач попадает в лог-файл платформы.
4. Ошибки в фоновых задачах
Фоновая задача не вызовет ошибку в основном потоке. Ошибка будет только в логе.
11.6. Best Practices
- Не злоупотребляйте частыми расписаниями — CRON "*/1 * * * * *" может создать высокую нагрузку
- Для длительных операций используйте фоновые задачи — не заставляйте пользователя ждать
- Логируйте начало и конец работы расписания для отладки
- Обрабатывайте ошибки внутри фоновых задач — иначе вы не узнаете, что пошло не так
- Не создавайте расписания, которые могут пересекаться — если задача выполняется дольше интервала, возможны коллизии
- Используйте флаги для предотвращения параллельного выполнения одной и той же задачи
- Тестируйте расписания с малыми интервалами при разработке, а в production ставьте реальные значения