Работа с задачами (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() следует использовать в следующих случаях:

  1. Шаблоны с транспортом LOCAL - когда шаблон выполняется локально на сервере SHM
  2. Явное управление результатом - когда необходимо точно указать статус выполнения задачи
  3. Условная логика - когда результат зависит от условий внутри шаблона
  4. Задачи автоматизации - для отчетности о выполнении массовых операций

Особенности

  • Если в шаблоне не вызван 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 ) }}

Типичные сценарии использования

  1. Пересоздание услуги после изменения шаблона - когда изменился шаблон создания и нужно применить изменения к существующим услугам

  2. Обновление конфигурации - после изменения настроек услуги требуется повторное выполнение события активации

  3. Исправление ошибок - если при создании произошла ошибка, можно исправить параметры и запустить событие заново

  4. Миграция данных - при переносе услуг между серверами или изменении инфраструктуры

  5. Синхронизация состояния - когда нужно синхронизировать состояние услуги с внешней системой

Важные особенности

  • Метод event() автоматически создает задачи в spool для выполнения события
  • Если у услуги есть дочерние услуги в статусе PROGRESS, родительская услуга также перейдет в PROGRESS
  • События CHANGED и CHANGED_TARIFF не требуют специального статуса и могут вызываться напрямую
  • При выполнении события услуга автоматически переходит в статус PROGRESS, а после выполнения - в целевой статус
  • Приоритет задач для событий обычно установлен в 10 (высокий приоритет)

Предупреждения

⚠️ Внимание: Повторное выполнение событий может привести к дублированию ресурсов или конфликтам. Используйте этот метод осознанно и убедитесь, что ваши шаблоны событий корректно обрабатывают повторное выполнение.

⚠️ Статус REMOVED: События нельзя выполнить для удаленных услуг (статус REMOVED).

Связанные темы

Изменено 18.08.2026: dnk: добалвен us.event (7545c33)