> ## Documentation Index
> Fetch the complete documentation index at: https://docs.yume.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Каналы доставки

> Транспортный слой уведомлений: веб-доставка в реальном времени, мобильный push через Expo с деактивацией мёртвых токенов и их регулярной уборкой, Telegram-канал и сервис-обёртка пакетной отправки.

Полный перечень полей — в [глоссарии](/ru/logic/notifications/delivery-channels-glossary).

## Обзор

Эта страница описывает нижний, транспортный слой системы уведомлений — то, что физически доставляет сообщение до устройства получателя. Когда центральная логика решила «этому сотруднику нужно показать уведомление», она не отправляет ничего сама: она ставит в очередь одну из фоновых задач транспорта. Каждый из трёх каналов — веб, мобильный push и Telegram — обслуживается отдельной фоновой задачей, которая обращается к внешнему сервису доставки. Сверху к мобильному каналу добавлен вспомогательный сервис-обёртка и задача регулярной уборки «мёртвых» токенов устройств.

<Info>
  Веб-доставка и мобильный push решают разные задачи. Веб — это живое обновление списка уведомлений в браузере (появление, изменение и удаление карточки в реальном времени). Мобильный push — это системное всплывающее уведомление на телефоне. Telegram — резервный/служебный канал через бота. Один и тот же логический факт может уйти сразу по нескольким каналам.
</Info>

## Три канала доставки

### Веб (реальное время в браузере)

Задача веб-уведомления публикует сообщение в именованный канал сервиса реального времени (Ably) через его HTTP-интерфейс. Публикация уходит в приоритетную очередь фоновых задач. У сообщения есть три параметра:

| Поле        | Тип   | Назначение                                                                                   |
| ----------- | ----- | -------------------------------------------------------------------------------------------- |
| Канал       | текст | Имя канала, в который публикуется сообщение; браузер получателя подписан именно на него      |
| Данные      | текст | Полезная нагрузка (тело сообщения), которую получит веб-клиент                               |
| Имя события | текст | «обновление» по умолчанию (добавить или обновить карточку) либо «удаление» (убрать карточку) |

Имя события — это ключевой переключатель поведения на стороне браузера. При событии обновления веб-клиент показывает или обновляет карточку уведомления. При событии удаления веб-клиент убирает карточку из списка. Второй вариант позволяет убрать карточку из ленты в реальном времени — например, когда общее уведомление уже прочитал один из сотрудников и его нужно снять у остальных.

Аутентификация в сервисе реального времени выполняется парой «ключ доступа + секрет», заданной в настройках приложения.

<Warning>
  Задача веб-доставки не проверяет ответ сервиса реального времени и ничего не возвращает. Если публикация не удалась (сервис недоступен, неверный ключ, сетевой сбой), задача завершится молча — повторной попытки нет, ошибка нигде не фиксируется как результат. Веб-канал считается «доставкой с максимальными усилиями», а не гарантированной.
</Warning>

### Мобильный push (Expo)

Задача мобильного push принимает список получателей и идентификатор компании, находит их устройства и рассылает системные уведомления через инфраструктуру Expo. Полный набор параметров:

| Поле                         | Тип     | Назначение                                                                            |
| ---------------------------- | ------- | ------------------------------------------------------------------------------------- |
| Идентификаторы пользователей | список  | Получатели push; без них задача сразу вернёт ошибку                                   |
| Идентификатор компании       | число   | Компания, по которой отбираются токены устройств; без него задача сразу вернёт ошибку |
| Заголовок                    | текст   | Заголовок уведомления                                                                 |
| Текст                        | текст   | Тело уведомления                                                                      |
| Данные                       | словарь | Дополнительная полезная нагрузка (по умолчанию пусто)                                 |
| Звук                         | текст   | Звук уведомления; по умолчанию системный звук                                         |
| Бейдж                        | число   | Счётчик на иконке приложения (необязательно)                                          |
| Канал Android                | текст   | Идентификатор канала уведомлений на Android (необязательно)                           |

Порядок работы задачи:

1. **Проверка входных данных.** Если не передан список получателей — возвращается ошибка «нужны получатели». Если не передан идентификатор компании — ошибка «нужна компания». Это обязательные поля.
2. **Поиск токенов.** Задача выбирает только *активные* push-токены устройств, принадлежащие переданной компании и указанным пользователям. Обратите внимание: отбор идёт одновременно по компании и по пользователям — токен «чужой» компании не будет использован, даже если пользователь совпал.
3. **Пустой результат — это успех.** Если активных токенов не нашлось, задача возвращает успешный результат с пометкой «активных токенов нет». Отсутствие устройства у получателя не считается ошибкой.
4. **Рассылка.** Токены передаются в сервис Expo-пушей, который отправляет уведомления пачкой и возвращает сводку: сколько доставлено, сколько с ошибками, и перечень ошибок с указанием проблемного токена.
5. **Деактивация «мёртвых» токенов.** Задача просматривает список ошибок. Если ошибка по конкретному токену содержит признак недействительного или незарегистрированного устройства, токен помечается как неактивный. Это защищает от повторных попыток слать уведомления на удалённые приложения и разлогиненные устройства.

<Note>
  Деактивация срабатывает только на две конкретные причины: недействительный токен и незарегистрированное устройство. Прочие ошибки (например, временный сбой сервиса Expo) токен не отключают — устройство остаётся активным и получит следующие уведомления.
</Note>

Любое непредвиденное исключение внутри задачи перехватывается: задача не падает, а возвращает результат с признаком неуспеха и текстом ошибки, и записывает ошибку в журнал.

### Telegram

Задача Telegram-уведомления отправляет текст сообщения через API Telegram-бота (метод отправки сообщения). Параметры:

| Поле               | Тип   | Назначение                                                        |
| ------------------ | ----- | ----------------------------------------------------------------- |
| Текст              | текст | Тело сообщения; разметка интерпретируется как HTML                |
| Токен бота         | текст | Токен Telegram-бота; по умолчанию берётся из настроек приложения  |
| Идентификатор чата | текст | Получатель; по умолчанию — служебный канал из настроек приложения |

Значения токена бота и чата по умолчанию подставляются из настроек, поэтому задачу можно вызывать как для обычной доставки конкретному пользователю (передав его чат), так и для служебных сообщений в общий канал (не передавая ничего). Сообщение отправляется в режиме HTML-разметки, что позволяет использовать простое форматирование в тексте. Задача возвращает код ответа Telegram и имеет увеличенный лимит времени выполнения (до 1 часа).

<Warning>
  Значения токена бота и получателя по умолчанию вычисляются один раз при загрузке кода задачи, а не при каждом вызове. Если эти настройки меняются во время работы приложения, значения по умолчанию не обновятся до перезапуска процесса.
</Warning>

## Сервис Expo-пушей

Мобильная задача не общается с Expo напрямую — между ними стоит сервис-обёртка над клиентом Expo. Он существует в единственном экземпляре на процесс и предоставляет два способа отправки.

**Отправка на список токенов.** Для каждого токена формируется отдельное сообщение (заголовок, текст, данные, звук, бейдж, канал Android), после чего все сообщения публикуются одной пачкой. Затем сервис разбирает ответы по каждому сообщению и считает:

* сколько отправок успешны;
* сколько с ошибками;
* перечень ошибок, где для каждой указан проблемный токен и текст ошибки.

Итоговая сводка помечается общим признаком успеха только если *ни одной* ошибки не было. Именно этот перечень ошибок мобильная задача затем использует для деактивации недействительных токенов.

**Отправка на один токен** — это просто обёртка: она вызывает пакетную отправку со списком из одного токена.

Сервис устойчив к сбоям: ошибки уровня сервера Expo и ошибки «билета» доставки, а также любые прочие исключения перехватываются и превращаются в результат с признаком неуспеха и описанием причины — сервис не роняет вызвавшую его задачу.

<Note>
  Пустой список токенов на входе сервиса возвращает результат с признаком неуспеха и пояснением «токены не переданы». При этом сама мобильная задача до сервиса в таком случае обычно не доходит — она раньше возвращает «активных токенов нет» как успех. То есть один и тот же факт «нет токенов» трактуется по-разному в зависимости от того, где остановилась цепочка.
</Note>

## Уборка неактивных токенов

Отдельная регулярная задача очищает базу от «мёртвых» устройств. Она удаляет push-токены, которые одновременно:

* помечены как неактивные, и
* не обновлялись более 30 дней.

Порог отсечения — текущий момент минус 30 дней по дате последнего изменения записи. Задача считает и записывает в журнал количество удалённых токенов и возвращает его в результате. В отличие от задач доставки, эта задача работает в обычной фоновой очереди, а не в приоритетной.

<Info>
  Деактивация и удаление — это два разных шага. Мобильная задача при недоставке лишь *помечает* токен неактивным (он остаётся в базе). Физически удаляет запись только регулярная уборка, и лишь спустя 30 дней неактивности. Такая отсрочка даёт «окно», в течение которого устройство может снова активироваться (например, пользователь переустановил и перезашёл в приложение).
</Info>

## Как это используется

Транспортные задачи — это конечные исполнители «веера доставки». Центральная логика уведомлений сама решает, кому и по каким каналам слать, а затем ставит соответствующие задачи в очередь: веб-задачу для живого обновления браузера, мобильную — для push на телефоны, Telegram-задачу — для сообщения в мессенджер. Веб-задача с событием удаления дополнительно позволяет убрать уведомление из ленты после того, как его прочитал один сотрудник.

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

## Особенности поведения

* Токены отбираются одновременно по компании и по списку пользователей, поэтому токен пользователя, зарегистрированный под другой компанией, использован не будет.
* Отсутствие активных токенов у получателя мобильная задача считает успехом, а не ошибкой доставки.
* Один и тот же факт «нет токенов» трактуется по-разному: мобильная задача возвращает его как успех, а сервис пакетной отправки — как неуспех с пояснением «токены не переданы».
* Сводка сервиса помечается общим признаком успеха только если среди всех токенов пачки не было ни одной ошибки доставки.
* Сервис пакетной отправки существует в единственном экземпляре на процесс и не роняет вызвавшую задачу: все ошибки перехватываются и возвращаются как результат с признаком неуспеха.
* Задачи доставки работают в приоритетной очереди, а регулярная уборка неактивных токенов — в обычной фоновой очереди.

## Связанные страницы

<CardGroup cols={2}>
  <Card title="Глоссарий: Каналы доставки" icon="book" href="/ru/logic/notifications/delivery-channels-glossary">
    Полный перечень полей и терминов транспортного слоя доставки уведомлений.
  </Card>

  <Card title="Уведомления (доставка и доступ)" icon="bell" href="/ru/logic/notifications">
    Обзорная страница модуля уведомлений и переход ко всем его разделам.
  </Card>

  <Card title="Модель и веер доставки" icon="sitemap" href="/ru/logic/notifications/model-dispatch">
    Модели уведомления и его адресатов, сигнал сохранения и разветвление доставки по каналам с учётом доступов пользователей.
  </Card>

  <Card title="Создание и группировка" icon="layer-group" href="/ru/logic/notifications/creation-grouping">
    Фоновые задачи создания уведомлений: одиночные, обновление по объекту и группировка в 30-минутном окне с накоплением счётчика и сообщений.
  </Card>

  <Card title="Чтение, архивация и список" icon="envelope-open" href="/ru/logic/notifications/read-archive">
    Списки, счётчик непрочитанных, отметка прочтения и архивация, включая логику «кто первый» для общих уведомлений и фильтры.
  </Card>

  <Card title="Push-токены устройств" icon="mobile-screen" href="/ru/logic/notifications/push-tokens">
    Регистрация и отписка push-токенов мобильных устройств пользователя с уникальностью по устройству и типом платформы.
  </Card>

  <Card title="Привязка Telegram" icon="paper-plane" href="/ru/logic/notifications/telegram-link">
    Привязка и отвязка аккаунта сотрудника к Telegram-боту по одноразовому коду верификации.
  </Card>

  <Card title="Доступ и настройки" icon="sliders" href="/ru/logic/notifications/access-settings">
    Матрица доступов «источник × тема» на пользователя, перечни источников и тем и массовое редактирование настроек уведомлений.
  </Card>
</CardGroup>
