Работа с задачами (task)
Объект task предоставляет методы для управления выполнением задач в шаблонах.
task.answer()
Метод task.answer() используется для явного указания результата выполнения задачи из шаблона. Это особенно важно при использовании транспорта LOCAL, когда код выполняется непосредственно на сервере SHM.
Синтаксис
{{ task.answer( status = STATUS, msg = MESSAGE ) }}
Параметры
| Параметр | Описание | Обязательный |
|---|---|---|
status |
Статус выполнения задачи | Да |
msg |
Сообщение о результате выполнения | Нет |
Статусы задач
| Статус | Описание |
|---|---|
TASK_SUCCESS |
Задача выполнена успешно |
TASK_FAIL |
Задача завершилась с ошибкой |
TASK_STUCK |
Задача застряла (требует ручного вмешательства) |
Примеры использования
Успешное выполнение
{{ user.add_bonus( 100, 'Акция' ) }}
{{ task.answer(
status = TASK_SUCCESS
msg = 'Бонусы начислены успешно'
) }}
Выполнение с ошибкой
{{ IF user.balance < 0 }}
{{ task.answer(
status = TASK_FAIL
msg = 'Недостаточно средств на балансе'
) }}
{{ END }}
Условное выполнение
{{ IF us.status == 'ACTIVE' }}
{{ us.block }}
{{ task.answer(
status = TASK_SUCCESS
msg = 'Услуга успешно заблокирована'
) }}
{{ ELSE }}
{{ task.answer(
status = TASK_FAIL
msg = 'Услуга не активна'
) }}
{{ END }}
Обработка списка пользователей
{{ count = 0 }}
{{ FOR u IN user.items }}
{{ us_list = u.us.filter( service_id = 5, status = 'ACTIVE' ).items }}
{{ IF us_list.size }}
{{ u.add_bonus( 100, 'Акция' ) }}
{{ count = count + 1 }}
{{ END }}
{{ END }}
{{ task.answer(
status = TASK_SUCCESS
msg = 'Начислено бонусов ' _ count _ ' пользователям'
) }}
Когда использовать task.answer()
Метод task.answer() следует использовать в следующих случаях:
- Шаблоны с транспортом LOCAL - когда шаблон выполняется локально на сервере SHM
- Явное управление результатом - когда необходимо точно указать статус выполнения задачи
- Условная логика - когда результат зависит от условий внутри шаблона
- Задачи автоматизации - для отчетности о выполнении массовых операций
Особенности
- Если в шаблоне не вызван
task.answer(), система автоматически определит статус выполнения - Параметр
msgсохраняется в логах и может быть использован для отладки - Статус
STUCKтребует ручного вмешательства администратора - Можно передавать дополнительные параметры для расширенной информации о результате
spool.add()
Метод spool.add() позволяет добавлять задачи в очередь выполнения (spool) непосредственно из шаблонов. Это мощный инструмент для создания цепочек задач и выполнения пользовательских шаблонов.
Синтаксис
{{ result = spool.add(
event = EVENT_OBJECT
settings = SETTINGS_OBJECT
prio = PRIORITY
) }}
Параметры
| Параметр | Описание | Обязательный |
|---|---|---|
event |
Объект события с параметрами выполнения | Да |
settings |
Объект с настройками задачи | Да |
prio |
Приоритет выполнения задачи (по умолчанию: 100) | Нет |
Объект event
| Поле | Описание | Обязательное |
|---|---|---|
name |
Название события (например, “UPDATE”, “CREATE”) | Да |
title |
Описание задачи (для логов и интерфейса) | Нет |
settings.transport |
Транспорт для выполнения (local, ssh, http) | Да |
Объект settings
| Поле | Описание | Обязательное |
|---|---|---|
template_id |
Идентификатор шаблона для выполнения | Да |
user_service_id |
ID услуги пользователя (если нужен контекст) | Нет |
server_id |
ID сервера для выполнения | Нет |
Приоритет задач
Приоритет (prio) определяет порядок выполнения задач в очереди:
- Меньшее значение = выше приоритет = задача выполнится раньше
- Большее значение = ниже приоритет = задача выполнится позже
- По умолчанию: 100
Примеры значений:
1- очень высокий приоритет (критичные задачи)50- высокий приоритет100- обычный приоритет (по умолчанию)200- низкий приоритет500- очень низкий приоритет (фоновые задачи)
Примеры использования
Выполнение пользовательского шаблона
Создание задачи для выполнения собственного шаблона с транспортом LOCAL:
{{ result = spool.add(
event = {
name = "UPDATE"
title = "Установка бесплатного тарифа"
settings = { transport = 'local' }
}
settings = {
template_id = 'my_template'
user_service_id = us.id
}
) }}
Задача с высоким приоритетом
Создание задачи, которая должна выполниться в первую очередь:
{{ result = spool.add(
event = {
name = "URGENT_UPDATE"
title = "Срочное обновление конфигурации"
settings = { transport = 'local' }
}
settings = {
template_id = 'urgent_config_update'
user_service_id = us.id
}
prio = 10
) }}
Фоновая задача с низким приоритетом
Создание фоновой задачи для статистики:
{{ result = spool.add(
event = {
name = "STATS"
title = "Сбор статистики"
settings = { transport = 'local' }
}
settings = {
template_id = 'collect_stats'
}
prio = 500
) }}
Массовое создание задач для пользователей
Создание задач для каждого пользователя с активной услугой:
{{ FOR u IN user.items }}
{{ us_list = u.us.filter( service_id = 5, status = 'ACTIVE' ).items }}
{{ IF us_list.size }}
{{ result = spool.add(
event = {
name = "BONUS_AWARD"
title = "Начисление бонусов пользователю " _ u.login
settings = { transport = 'local' }
}
settings = {
template_id = 'award_bonus'
user_service_id = us_list.first.id
}
) }}
{{ END }}
{{ END }}
Цепочка задач
Создание последовательности задач с разными приоритетами:
{{# Первая задача - подготовка данных }}
{{ result1 = spool.add(
event = {
name = "PREPARE"
title = "Подготовка данных"
settings = { transport = 'local' }
}
settings = {
template_id = 'prepare_data'
user_service_id = us.id
}
prio = 10
) }}
{{# Вторая задача - обработка (выполнится после первой) }}
{{ result2 = spool.add(
event = {
name = "PROCESS"
title = "Обработка данных"
settings = { transport = 'local' }
}
settings = {
template_id = 'process_data'
user_service_id = us.id
}
prio = 20
) }}
{{# Третья задача - отправка уведомления (выполнится последней) }}
{{ result3 = spool.add(
event = {
name = "NOTIFY"
title = "Отправка уведомления"
settings = { transport = 'local' }
}
settings = {
template_id = 'send_notification'
user_service_id = us.id
}
prio = 30
) }}
Возвращаемое значение
Метод возвращает объект добавленной задачи с полями:
id- идентификатор созданной задачиstatus- статус задачи (обычноTASK_NEW)- другие поля задачи
Особенности
- Задачи выполняются асинхронно в порядке приоритета
- Задачи с одинаковым приоритетом выполняются в порядке добавления (по ID)
- Можно создавать задачи для выполнения на других серверах, указав
server_id - Поле
titleсохраняется в логах и отображается в административном интерфейсе - Задачи можно отслеживать через административный интерфейс SHM
us.make_custom_event()
Метод us.make_custom_event() - это удобный способ создания пользовательских событий для услуги. Он автоматически добавляет контекст услуги (user_service_id и server_id) и создает задачу в очереди выполнения.
Синтаксис
{{ result = us.make_custom_event(
name = EVENT_NAME
title = DESCRIPTION
transport = TRANSPORT
template_id = TEMPLATE_ID
prio = PRIORITY
delay = DELAY_SECONDS
settings = SETTINGS_OBJECT
) }}
Параметры
| Параметр | Описание | Обязательный | По умолчанию |
|---|---|---|---|
name |
Название события | Нет | ‘custom’ |
title |
Описание события для логов | Нет | ‘custom event’ |
transport |
Транспорт для выполнения (local, ssh, http) | Нет* | Из сервера услуги |
template_id |
Идентификатор шаблона для выполнения | Нет* | Из сервера услуги |
prio |
Приоритет выполнения задачи | Нет | 100 |
delay |
Задержка выполнения в секундах | Нет | 0 |
settings |
Дополнительные настройки задачи | Нет | {} |
* Хотя бы один из параметров (transport + template_id или сервер услуги) должен быть указан.
Автоматически добавляемые параметры
Метод автоматически добавляет:
user_service_id- ID текущей услугиserver_id- ID сервера из настроек услуги (если указан)
Приоритет и задержка
- Приоритет (
prio): меньшее значение = выше приоритет (по умолчанию 100) - Задержка (
delay): время в секундах до начала выполнения задачи
Примеры использования
Базовое использование
Создание пользовательского события для отправки промокода:
{{ result = us.make_custom_event(
name = 'PROMOCODE_SEND'
title = 'Отправка промокода'
transport = 'local'
template_id = 'alp_promo_send'
prio = 100
settings = {
promo_code = 'SUMMER2024'
discount = 20
}
) }}
Событие с высоким приоритетом
Создание срочной задачи для немедленного выполнения:
{{ result = us.make_custom_event(
name = 'URGENT_UPDATE'
title = 'Срочное обновление конфигурации'
transport = 'local'
template_id = 'urgent_config'
prio = 10
) }}
Отложенное событие
Создание задачи, которая выполнится через 1 час (3600 секунд):
{{ result = us.make_custom_event(
name = 'REMINDER'
title = 'Напоминание об оплате'
transport = 'local'
template_id = 'payment_reminder'
delay = 3600
settings = {
reminder_type = 'payment_due'
}
) }}
Выполнение для нескольких услуг
Создание событий для всех активных услуг определенной категории:
{{ FOR service IN user.us.filter( status = 'ACTIVE', service_id = 5 ).items }}
{{ result = service.make_custom_event(
name = 'NOTIFICATION'
title = 'Уведомление для услуги ' _ service.name
transport = 'local'
template_id = 'service_notification'
settings = {
message = 'Ваша услуга успешно продлена'
}
) }}
{{ END }}
Событие с дополнительными настройками
Передача сложных данных в settings:
{{ result = us.make_custom_event(
name = 'DATA_SYNC'
title = 'Синхронизация данных'
transport = 'local'
template_id = 'data_sync'
prio = 200
settings = {
sync_type = 'incremental'
sources = ['db1', 'db2']
options = {
verify = true
backup = true
}
}
) }}
Цепочка событий с задержками
Создание последовательности событий с разными задержками:
{{# Сразу - подготовка }}
{{ r1 = us.make_custom_event(
name = 'PREPARE'
title = 'Подготовка данных'
transport = 'local'
template_id = 'prepare'
prio = 10
) }}
{{# Через 5 минут - обработка }}
{{ r2 = us.make_custom_event(
name = 'PROCESS'
title = 'Обработка данных'
transport = 'local'
template_id = 'process'
prio = 20
delay = 300
) }}
{{# Через 10 минут - уведомление }}
{{ r3 = us.make_custom_event(
name = 'NOTIFY'
title = 'Отправка уведомления'
transport = 'local'
template_id = 'notify'
prio = 30
delay = 600
) }}
Использование в событиях
Создание дополнительного события при активации услуги:
{{# В шаблоне события ACTIVATE }}
{{ IF us.service.id == 5 }}
{{ result = us.make_custom_event(
name = 'WELCOME_EMAIL'
title = 'Отправка приветственного письма'
transport = 'local'
template_id = 'welcome_email'
delay = 60
) }}
{{ END }}
Возвращаемое значение
Метод возвращает объект созданной задачи или undef при ошибке.
Отличия от spool.add()
us.make_custom_event() - это упрощенная обертка над spool.add(), специально созданная для работы с событиями услуг пользователя.
Сравнительная таблица
| Характеристика | us.make_custom_event() | spool.add() |
|---|---|---|
| Контекст | Автоматически добавляет user_service_id и server_id | Требует явного указания всех параметров |
| Синтаксис | Плоский список параметров | Вложенная структура (event + settings) |
| Использование | Для событий конкретной услуги | Для любых задач (общие или специфичные) |
| Сервер | Берется из настроек услуги | Нужно указывать явно в settings.server_id |
| Параметр задержки | delay (в секундах) |
delayed (в секундах) + executed |
| Транспорт | Напрямую в параметрах | В event.settings.transport |
| Гибкость | Ограниченная (стандартные сценарии) | Полный контроль над всеми аспектами |
| Простота | Высокая (меньше кода) | Средняя (больше параметров) |
Примеры эквивалентного кода
Одно и то же действие выполненное разными способами:
С помощью us.make_custom_event() (упрощенно):
{{ result = us.make_custom_event(
name = 'PROMOCODE_SEND'
title = 'Отправка промокода'
transport = 'local'
template_id = 'alp_promo_send'
prio = 100
) }}
Тот же результат через spool.add() (полный контроль):
{{ result = spool.add(
event = {
name = "PROMOCODE_SEND"
title = "Отправка промокода"
settings = { transport = 'local' }
}
settings = {
template_id = 'alp_promo_send'
user_service_id = us.id
server_id = us.server.id
}
prio = 100
) }}
Как видно, us.make_custom_event() автоматически подставляет user_service_id и server_id, что делает код короче и проще.
Когда использовать
Используйте us.make_custom_event() когда:
- ✅ Работаете в контексте услуги пользователя (в шаблонах событий, автоматизациях)
- ✅ Услуга привязана к серверу и нужен его контекст
- ✅ Нужна простота и скорость разработки
- ✅ Создаете стандартные события для услуг
- ✅ Хотите меньше кода и автоматическое заполнение контекста
Используйте spool.add() когда:
- ✅ Создаете задачи не связанные с конкретной услугой
- ✅ Нужно создать задачу для другого пользователя или услуги
- ✅ Требуется нестандартная структура события
- ✅ Создаете системные или административные задачи
- ✅ Нужен полный контроль над всеми параметрами события
- ✅ Работаете вне контекста услуги (например, в задачах автоматизации для всех пользователей)
Особенности
- Если не указан
transportиtemplate_id, они будут взяты из настроек сервера услуги - Метод автоматически добавляет
user_service_idтекущей услуги server_idдобавляется автоматически, если услуга связана с сервером- Задержка (
delay) полезна для отложенных уведомлений и напоминаний - Дополнительные данные в
settingsдоступны в шаблоне черезtask.settings
us.event()
Метод us.event() позволяет повторно запустить выполнение стандартных событий для услуги пользователя. Это полезно когда нужно повторить выполнение события, например, после изменения настроек или при необходимости пересоздания ресурсов.
Синтаксис
{{ us.event( EVENT_NAME ) }}
Параметры
| Параметр | Описание | Обязательный |
|---|---|---|
EVENT_NAME |
Название стандартного события | Да |
Доступные события
| Константа | Значение | Описание |
|---|---|---|
EVENT_CREATE |
CREATE | Создание услуги |
EVENT_ACTIVATE |
ACTIVATE | Активация услуги |
EVENT_PROLONGATE |
PROLONGATE | Продление услуги |
EVENT_BLOCK |
BLOCK | Блокировка услуги |
EVENT_REMOVE |
REMOVE | Удаление услуги |
EVENT_CHANGED |
CHANGED | Изменение услуги |
EVENT_CHANGED_TARIFF |
CHANGED_TARIFF | Изменение тарифа |
Статус PROGRESS и выполнение событий
Для повторного выполнения большинства событий услуга должна находиться в статусе STATUS_PROGRESS или в соответствующем событию статусе.
Важно: Статус PROGRESS позволяет запускать любое событие, что делает его универсальным для повторного выполнения.
Правила выполнения событий по статусам
| Событие | Разрешенные статусы |
|---|---|
EVENT_CREATE |
INIT, NOT PAID, PROGRESS |
EVENT_PROLONGATE |
ACTIVE, PROGRESS |
EVENT_BLOCK |
ACTIVE, PROGRESS |
EVENT_ACTIVATE |
BLOCK, PROGRESS |
EVENT_REMOVE |
ACTIVE, BLOCK, PROGRESS |
EVENT_CHANGED |
Любой (кроме REMOVED) |
EVENT_CHANGED_TARIFF |
Любой (кроме REMOVED) |
Примеры использования
Повторное выполнение события CREATE
Классический случай - необходимость пересоздать услугу (например, после изменения параметров):
{{# Переводим услугу в статус PROGRESS }}
{{ us.set( status = STATUS_PROGRESS ) }}
{{# Запускаем событие CREATE повторно }}
{{ us.event( EVENT_CREATE ) }}
Повторная активация услуги
Повторная активация может потребоваться для обновления конфигурации:
{{ us.set( status = STATUS_PROGRESS ) }}
{{ us.event( EVENT_ACTIVATE ) }}
Принудительное обновление конфигурации
Использование события CHANGED для обновления без изменения статуса:
{{# CHANGED можно вызвать без изменения статуса }}
{{ us.event( EVENT_CHANGED ) }}
Повторное создание после изменения настроек
Изменяем настройки и пересоздаем услугу:
{{# Изменяем настройки услуги }}
{{ us.set_settings(
new_param = 'value'
updated = true
) }}
{{# Переводим в PROGRESS и пересоздаем }}
{{ us.set( status = STATUS_PROGRESS ) }}
{{ us.event( EVENT_CREATE ) }}
Пересоздание всех услуг определенной категории
Массовое пересоздание услуг:
{{ FOR service IN user.us.filter( service_id = 5, status = 'ACTIVE' ).items }}
{{ service.set( status = STATUS_PROGRESS ) }}
{{ service.event( EVENT_CREATE ) }}
{{ END }}
Событие с проверкой текущего статуса
Безопасное выполнение события с проверкой:
{{ IF us.status == 'ACTIVE' }}
{{ us.set( status = STATUS_PROGRESS ) }}
{{ us.event( EVENT_PROLONGATE ) }}
{{ ELSE }}
{{ task.answer(
status = TASK_FAIL
msg = 'Услуга не активна, невозможно выполнить продление'
) }}
{{ END }}
Цепочка событий
Выполнение нескольких событий последовательно:
{{# Сначала CHANGED для обновления статуса }}
{{ us.event( EVENT_CHANGED ) }}
{{# Затем пересоздаем }}
{{ us.set( status = STATUS_PROGRESS ) }}
{{ us.event( EVENT_CREATE ) }}
Типичные сценарии использования
-
Пересоздание услуги после изменения шаблона - когда изменился шаблон создания и нужно применить изменения к существующим услугам
-
Обновление конфигурации - после изменения настроек услуги требуется повторное выполнение события активации
-
Исправление ошибок - если при создании произошла ошибка, можно исправить параметры и запустить событие заново
-
Миграция данных - при переносе услуг между серверами или изменении инфраструктуры
-
Синхронизация состояния - когда нужно синхронизировать состояние услуги с внешней системой
Важные особенности
- Метод
event()автоматически создает задачи в spool для выполнения события - Если у услуги есть дочерние услуги в статусе PROGRESS, родительская услуга также перейдет в PROGRESS
- События
CHANGEDиCHANGED_TARIFFне требуют специального статуса и могут вызываться напрямую - При выполнении события услуга автоматически переходит в статус PROGRESS, а после выполнения - в целевой статус
- Приоритет задач для событий обычно установлен в 10 (высокий приоритет)
Предупреждения
⚠️ Внимание: Повторное выполнение событий может привести к дублированию ресурсов или конфликтам. Используйте этот метод осознанно и убедитесь, что ваши шаблоны событий корректно обрабатывают повторное выполнение.
⚠️ Статус REMOVED: События нельзя выполнить для удаленных услуг (статус REMOVED).