Урок 24. Планировщик задач
Last updated
Last updated
Если хотите начать практику с этого урока, то вам необходимо развернуть учебный проект по инструкции в статье Разворачивание проекта.
При разворачивании проекта используйте backup базы данных, который можете найти в архиве из раздела Ответы прошлого урока. Скопируйте папки Forms, Workflow и Patterns в папку с развернутым проектом, например, в папку D:\WT\Projects\Template\Projects\1. Template.
Инструкция по подключению шаблонов находится по ссылке.
В прошлом уроке мы узнали про планировщик задач <Scheduler>
, который по расписанию или при старте сервера выполняет задачи. И создали задачу на отправку писем с поздравлениями при старте сервера:
Когда мы первый раз запустили сервер с задачей о рассылки писем, движок создал в базе данных таблицу public.schedule. В эту таблицу сервер будет писать последнее время выполнения каждой задачи. После выполнения нашей задачи в таблице появилась запись:
Для задач можно настроить расписание, по которому они будут выполнятся. Есть два способа задать расписание:
прописать его в серверном xml-файле, тогда разработчик будут сам его редактировать при необходимости;
вынести настройки расписания в базу данных и через интерфейс приложения позволить пользователю самому управлять расписанием.
Для того чтобы задать статического расписания для выполнения задачи, изменим код следующим образом:
У атрибута Type
тэга <Condition>
сменили значение на Values и добавили вложенные тэги с настройкой времени. Доступны тэги: <Month>
, <Day>
, <Hour>
, <Minute>
и <Second>
.
В тэге <Hour>
мы задали период, в пределах которого будет выполняться задача, а в тэге <Minute>
указали интервал, через который задача будет повторяться. Т.е. планировщик будет запускать нашу задачу каждый день в период с 10 до 15 часов с повтором каждые 20 минут.
Время указывается в часовом поясе сервера!
У тэга <Task>
есть необязательный вложенный тэг <ExecutionStrategy>
, который задает правило обработки пропущенных плановых запусков. Если тэг не указан, то будет использоваться значение ExecuteMissed, которое означает, что будут выполняться все пропущенные запуски.
В нашем случае нет необходимости выполнять все пропущенный запуски. Достаточно, чтобы выполнился последний пропущенный. Поэтому будем использовать значение ExecuteLastMissed для тэга <ExecutionStrategy>
:
Для динамических расписаний у атрибута Type
тэга <Condition>
используется значение Query. В этом случае необходимо прописывать sql-запрос, с помощью которого будем получать настройки интервала выполнения задачи. Sql-запрос должен возвращать хотя бы один столбец с именем из списка: Month, Day, Hour, Minute, Second.
Давайте в таблицу template.settings добавим колонку, которую будем использовать для хранения времени отправки писем:
Переделаем синтаксис задачи:
Теперь наша задача будет выполняться при старте сервера, если был пропущен предыдущий запуск, и каждый день один раз в определенное время, которое указано в настройках.
Скорректируйте форму настроек, добавив на вкладку "Email" поле для редактирования времени отправки писем и CheckBox для включения/отключения автоматической рассылки:
Добавим в таблицу template.settings признак автоматической отправки:
Ранее в уроках упоминалось, что платформа только дату и только время из DateTimePicker передает на сервер без приведения к UTC. Таким образом, время запуска рассылки будет сохранено в базе данных так, как его указали на форме. И сервер будет воспринимать это время в своем часовом поясе.
Чтобы этого не происходило, необходимо вручную скорректировать время при сохранении в базу данных (SettingsUpdateSqlQuery), используя для этого функцию:
Соответствующим образом необходимо преобразовывать время, которое получаем из базы данных и передаем на форму настроек (SettingsSelectSqlQuery):
После того, как мы обновили время запуска рассылки, необходимо перезапустить задачу в планировщике, чтобы она подтянула новые настройки.
Вернемся в серверный xml-файл и создадим команду SchedulerConditionRefreshCommand, которая будет обновлять расписание задачи:
Эту команду будем вызывать с формы настроек. А значит необходимо добавить команду в соответствующее разрешение, чтобы пользователь имел права доступа к ней:
Теперь вернемся на форму настроек (TemplateSettings.xml) и добавим условие, проверяющее, изменилось ли время запуска рассылки:
Чтобы с клиентской формы можно было вызывать команду на сервере, в платформе реализована команда CallCommand. Давайте создадим такую на форме настроек, чтобы на сервере вызывать команду HappyBirthdayEmailSendTaskSchedulerConditionRefreshCommand:
И добавим ее вызов в последовательность команд на сохранение изменений (SaveSequentialCommand).
Вернемся в серверный файл Template.xml и добавим условие проверки, включена ли автоматическая рассылка поздравлений. Для этого перед тэгом <Commands>
добавим тэг <Conditions>
, в который добавим условие типа SqlQueryCondition:
Скорректируем задачу рассылки писем, добавив проверку условия:
Задача будет выполняться по расписанию, но сама команда будет выполняться, если пользователь включит настройку.
В этом уроке мы рассмотрели, как настроить планировщик задач на стороне сервера и как динамически менять параметры расписания задач. Также узнали о том, как с клиентских форм вызывать команды на стороне сервера.
В архиве присутствуют xml-файлы форм и серверный xml-файл, также лежит бэкап базы данных и файл с запросами на изменение структуры базы данных - с помощью файлов можете проверить себя.