pull 25.400.0: массовое удаление каналов и эмодзи, которые ломали очередь пушей
Небольшой релиз с двумя очень прикладными вещами: bulk-удаление каналов и push-токенов пачкой и кодирование эмодзи в очереди пушей. Ломающих изменений нет — единственная правка сигнатуры совместима со старыми вызовами.
Удаление каналов пачкой
Появились два публичных метода:
\CPullChannel::DeleteByUsers(array $userIds, string $channelType = self::TYPE_PRIVATE): void;
\Bitrix\Pull\Model\PushTable::deleteByUsers(array $userIds): void;
Оба чистят b_pull_channel и b_pull_push чанками по 500 id, USER_ID = 0 пропускается, статический кэш CPullChannel сбрасывается. PushTable::deleteByUsers пишет прямой DELETE и не поднимает ORM-события удаления — если вы вешали хендлеры на удаление push-токенов, они здесь не сработают.
Сценарий очевиден: увольнение отдела, чистка неактивных, миграция портала. Раньше это был цикл с удалением по одному пользователю — на нескольких тысячах записей заметно.
Важная деталь, прямо прописанная комментарием в коде: уведомление клиентам нужно отправлять до вызова, а не после. После удаления канала слать пуш уже некуда — соединение, которому вы хотели сказать «переподключись», больше не адресуемо.
Порядок в вашем коде должен быть такой: сначала рассылка события клиентам (разлогин, переподключение — что уместно сценарию), затем DeleteByUsers(). Перепутаете — часть клиентов останется висеть на мёртвом канале до собственного таймаута.
Эмодзи в очереди пушей
В CPushManager поля MESSAGE, PARAMS и ADVANCED_PARAMS теперь прогоняются через Emoji::encode() при вставке в b_pull_push_queue и через Emoji::decode() при чтении агентом. Комментарий в коде объясняет причину: таблица может быть в utf8mb3.
Это старая боль MySQL: utf8 в его исторической версии — трёхбайтовый, а эмодзи требует четырёх. Сообщение со смайлом в такой таблице либо обрезается на первом эмодзи, либо валит INSERT ошибкой. Порталы, поднятые давно и не переведённые на utf8mb4, ловили ровно это — пуш с эмодзи не доезжал. Теперь символ хранится в закодированном виде и разворачивается при отправке.
Там же: проверка VoIP переписана с $message["ADVANCED_PARAMS"]["isVoip"] на !empty(...) — чтобы отсутствующий ключ не давал notice.
Сигнатуры
CPullChannel::getMany(array $userIds, ?string $channelType = self::TYPE_PRIVATE) — второй параметр стал nullable. Старые вызовы работают как раньше.
Что делать
- Замените свои циклы удаления каналов на
DeleteByUsers— но не забудьте про порядок: сначала уведомление, потом удаление. - Если у вас есть обработчики ORM-событий на
PushTable— учтите, что bulk-метод их не вызывает. - Если портал на
utf8mb3— обновление лечит пропадающие пуши с эмодзи, но перевести базу наutf8mb4всё равно стоит.