Аларм сценарии

Аларм-сценарии (или "алармы") — это архитектурный паттерн, позволяющий динамически изменять логику работы всего проекта или его частей в ответ на нештатные ситуации, такие как технические сбои, пиковы

Основная идея — централизованное управление состоянием проекта через глобальный аларм-флаг. В зависимости от этого флага, сценарии могут переключаться со стандартной логики на альтернативную (аларм-ветку).

Ключевые компоненты

  1. Аларм-флаг: Глобальная переменная, хранящая текущий статус аларма. Например, ALARM_PAYMENT_SYSTEM: true.

  2. Управляющий сниппет: Специальный сниппет для установки и снятия аларм-флагов. Это единая точка управления алармами.

  3. Проверяющий сниппет: Сниппет, который выполняется в начале ключевых сценариев, читает состояние аларм-флага и записывает его в контекст текущего пользователя.

  4. Реакция «Условие»: Блок, который проверяет флаг в контексте и направляет пользователя по стандартной или аларм-ветке.

Лучшая практика: Хранение флагов в projectStorage Для максимальной гибкости храните аларм-флаги в projectStorage. Это позволяет активировать и деактивировать алармы без необходимости вносить изменения в код сниппетов и делать новый релиз проекта.

Паттерн реализации

1. Управление аларм-флагами

Создайте отдельный сниппет (например, setAlarm), который будет использоваться для включения или выключения алармов. Его можно запускать вручную через тестовый чат для управления состоянием.

// snippet: setAlarm
async function snippet(core, context, projectStorage) {
  // Для включения аларма передайте в фактах: { "alarm_payment": true }
  // Для выключения: { "alarm_payment": false }
  const alarmStatus = context.get('alarm_payment');

  if (typeof alarmStatus === 'boolean') {
    // Устанавливаем флаг в projectStorage с TTL (Time To Live) в 1 день (86400 секунд)
    await projectStorage.set('ALARM_PAYMENT_SYSTEM', alarmStatus, 86400);
    core.sendText(`Статус аларма платежной системы установлен в: ${alarmStatus}`);
  } else {
    core.sendText('Некорректный статус аларма. Передайте true или false в факте alarm_payment.');
  }
}

2. Проверка аларм-флага в сценариях

В начале каждого сценария, который должен реагировать на аларм (например, в сценарии «Старт» или перед переводом на оператора), добавьте сниппет, который проверяет projectStorage.

// snippet: checkAlarm
async function snippet(core, context, projectStorage) {
  // Читаем флаг из projectStorage. Если его нет, считаем, что аларма нет (false).
  const isAlarmActive = await projectStorage.get('ALARM_PAYMENT_SYSTEM') || false;
  
  // Записываем статус в контекст текущего пользователя.
  context.set('payment_alarm_active', isAlarmActive);
}

3. Ветвление логики

Сразу после сниппета checkAlarm поставьте реакцию «Условие», которая будет проверять флаг в контексте.

  • Параметр: payment_alarm_active

  • Оператор: Равен

  • Значение: true

  • Ветка «Выполнено» ведет на аларм-логику (например, сообщение «В данный момент наблюдаются проблемы с оплатой. Мы уже работаем над решением.»).

  • Ветка «Не выполнено» (или else) ведет на стандартную логику сценария.

Примеры использования

Управление несколькими алармами

В сложных проектах может потребоваться управлять несколькими независимыми алармами (например, один для платежей, другой для службы доставки). Паттерн остается тем же, но управляющий сниппет модифицируется для работы с разными аларм-флагами.

Шаг 1: Создание универсального управляющего сниппета.

Этот сниппет сможет устанавливать или снимать любой аларм, имя которого передается в фактах.

// snippet: alarmManager
async function snippet(core, context, projectStorage) {
  // Ожидаемые факты: { "alarmName": "ALARM_DELIVERY", "alarmStatus": true }
  const { alarmName, alarmStatus } = context.get_all();

  if (alarmName && typeof alarmStatus === 'boolean') {
    // Устанавливаем флаг в projectStorage с TTL в 1 день
    await projectStorage.set(alarmName, alarmStatus, 86400);
    core.sendText(`Статус аларма '${alarmName}' установлен в: ${alarmStatus}`);
  } else {
    core.sendText('Ошибка: передайте { "alarmName": "...", "alarmStatus": true/false } в фактах.');
  }
}

Шаг 2: Проверка конкретного аларма в сценарии.

В нужном сценарии (например, в сценарии отслеживания доставки) вы используете проверяющий сниппет, который читает только нужный флаг.

// snippet: checkDeliveryAlarm
async function snippet(core, context, projectStorage) {
  const isDeliveryAlarm = await projectStorage.get('ALARM_DELIVERY') || false;
  context.set('delivery_alarm_active', isDeliveryAlarm);
}

После этого реакция «Условие» проверяет факт delivery_alarm_active и направляет пользователя по соответствующей ветке. Такой подход обеспечивает изоляцию и гибкое управление каждым алармом в проекте.

Практический пример: Полная реализация аларм-сценария

Рассмотрим полную реализацию аларм-сценария, состоящую из трех основных компонентов.

Компонент 1: Настройка переменных в личном кабинете

В личном кабинете устанавливаются следующие переменные:

Переменные состояния алармов (boolean):

  • alarm1 — состояние первого аларма (true/false)

  • alarm2 — состояние второго аларма (true/false)

  • alarm3 — состояние третьего аларма (true/false)

Переменные текстовок:

  • alarm1text — текст сообщения для первого аларма

  • alarm2text — текст сообщения для второго аларма

  • alarm3text — текст сообщения для третьего аларма

Компонент 2: Два сниппета

Сниппет 1: Отправка текстовок (sendAlarm)

Этот сниппет проверяет состояние алармов и отправляет соответствующие текстовки пользователю:

async function snippet(core = new Core(), context = new Context(), projectStorage = new ProjectStorage()) {
    // Инициализируем флаги отправки
    context.set('alarm1WasSent', false);
    context.set('alarm2WasSent', false);
    context.set('alarm3WasSent', false);

    // Проверяем и отправляем текстовки для активных алармов
    if (context.alarm1) {
        core.sendText(context.alarm1text);
        context.set('alarm1WasSent', true);
    }

    if (context.alarm2) {
        core.sendText(context.alarm2text);
        context.set('alarm2WasSent', true);
    }

    if (context.alarm3) {
        core.sendText(context.alarm3text);
        context.set('alarm3WasSent', true);
    }
}

Сниппет 2: Изменение состояния (changeAlarmStatus)

Этот сниппет проверяет, были ли отправлены какие-либо аларм-сообщения, и генерирует ошибку для перенаправления в соответствующую ветку:

async function snippet(core = new Core(), context = new Context(), projectStorage = new ProjectStorage()) {
    // Если хотя бы один аларм был отправлен, генерируем ошибку
    if (context.alarm1WasSent || context.alarm2WasSent || context.alarm3WasSent) {
        throw new Error();
    }
}

Компонент 3: Структура сценария

Сценарий строится по следующей схеме:

Логика работы:

  1. Стартовый триггер запускает первый сниппет sendAlarm

  2. Первый сниппет проверяет активные алармы и отправляет текстовки:

    • Успех: Переходит ко второму сниппету

    • Ошибка: Обработка выполнения сниппета

  3. Второй сниппет changeAlarmStatus проверяет флаги отправки:

    • Успех: Ни один аларм не был отправлен → продолжение обычного сценария

    • Ошибка: Хотя бы один аларм был отправлен → переход в ветку «Ошибка»

Последнее обновление