Вчера при разработке модуля использующего HLB и свои UserType поля наткнулся на интересный баг.
После добавления своего типа пользовательского поля, и добавление его в HL блок, стало появляться исключение описанное в сабже. ORM никак не желал верить в то что поле UF_MY_FIELD существует. Пришлось одевать чистые сапоги и лезть в ядро.
Решение
Не компилировать свои HLBTable (использующие ваши UserType поля подключаемые в модуле) через HighloadBlockTable::compileEntity(), a создавать их вручную.
Причина
Расследование началось именно с метода компиляции сущности HLB:
,так как мой HLBTable::getMap() возвращал только поле ID (это не типичный признак ошибки, может возвращать все поля до написанного вами поля). Там мы видим что запрос полей по идентификатору HLB так же, возвращает только поля до кастомного UserType поля.
Далее пришел к тому что в методе:
CUserTypeManager::GetUserFields();
, не формируется полный список полей так как для определённых типов возвращается FALSE
И вот мы подобрались багу, метод CUserTypeManager::GetUserType(); что бы было понятно вот скрин:
Другими словами тип кастомного пользовательского поля ищется в списке типов, до того как он туда попадает, было бы хуже если бы список не кэшировался, тогда бы нас ожидала рекурсия.
Именно поэтому нельзя компилировать HLBTable имеющие кастомные поля при include модуля.
А ещё...
Эта ошибка может возникнуть даже если кастомное поле не присвоено компилируемому HLB, причем пропасть может даже поле со стандартным типом, например string.
Причина вся в сортировке обработчиков события OnUserTypeBuildList, по умолчанию стандартные типы имеют сортировку 100, с такой же сортировкой добавляются ваши обработчики, в которых она не задана. В итоге обработчик созданного вами типа может быть вызван ранее обработки стандартных типов, и компиляция HLB произойдёт по не полному списку типов свойств.
Наткнулся на такую ошибку при наследовании от класса, полученного после HighloadBlockTable::compileEntity()
Однако есть решение. Необходимо переопределить все методы, которые будут использоваться и в которых возникает ошибка и организовать в них прямой вызов метода наследуемого класса
пример
namespace My\Entity;
class OrderTable extends \AOrderTable{
public static $parentClass = "\AOrderTable";
public static function getList($arParams){
return self::$parentClass::getList($arParams);
}
}
class Order extends OrderTable{}
где "\AOrderTable" - это результат компиляции highload блока
Якимов Антон, не делайте так никогда, изучите подробно статьи по ORM Битрикса, объявляйте сущности и их поля вручную, компиляция сущностей через HighloadBlockTable это плохо
Пользователи начали жаловаться что зависает приложение битрикс, помогает только завершение процесса и перезапуск. Диагностика проблемы показала что зависание происходит при обращении к поиску, а конкретно при выполнении вот этого запроса: /bitrix/components/bitrix/im.messenger/im.ajax.php?CONTACT_LIST&V=130
Проверил через последний хром, открыв desktop_app, он тоже зависает, конечно не весь как приложение битрикс, а только вкладка, которую он заботливо предлагает закрыть. Значит проблема не в приложении.
А оказалась проблема в функции быстрого поиска чатов. Эта функция загружает с сервера ВСЕ чаты, контакты, сотрудников и телефоны, доступные пользователю. А после она видимо формирует из них html контейнеры чтобы оперативно выводить при поиске.
Но дело в том, что при разработке не учитывалось масштабирование системы, и то что пользователей и чатов может быть очень много. Так например произошло в моем случае, и формирование ответа сервера мало того что занимало >9 секунд, так ещё и ответ весил 2,6 Мб, это всё был json с сотрудниками и чатами открытых линий и CRM:
Решение Сначала попытался отключить параметр "Включить предварительную загрузку всех пользователей портала для быстрого поиска" в настройках модуля Веб-мессенджер. Но это не помогло, так как отключился только запрос сотрудников, а чаты так и продолжили загружаться, плюс проявился ещё один баг, после отключения этой функции, но о нем ниже.
Пришлось опять лезть в ядро что бы поправить ошибку, оказалось что данные для ответа собирает метод \CIMContactList::GetList() Находится он в этом файле /home/bitrix/www/bitrix/modules/im/classes/general/im_contact_list.php:22 И оказывается он принимает параметр LOAD_CHATS который отвечает за загрузку всех доступных пользователю чатов, но видимо забыли вывести этот параметр в настройки модуля.
Предлагаю костылить следующе, в файле обработчике ajax запросов из веб-мессенджера /home/bitrix/www/bitrix/components/bitrix/im.messenger/im.ajax.php в строке 1165 добавляем передачу параметра LOAD_CHATS в метод \CIMContactList::GetList():
Добавляем так же что бы параметр брался из настроек, как и с сотрудниками, что бы можно было отключить. Соблюдаем странный перегон логической переменной в Y/N, что метод нас понял.
На этом всё, ждем исправлений от разработчиков, а пока они их не сделают придётся костылить это после каждого обновления модуля.
Дополнительный баг
А теперь баг о котором написал выше. Если отключить загрузку сотрудников в настройках модуля, то тогда перестаёт работать поиск при делегировании чатов открытых линий, так как он производит поиск только по локально сохранённым сотрудникам.
При этом при добавлении сотрудника в чат, поиск производится так же через запрос на сервер, но при делегировании только локально, забыли наверное. Я лезть в js не стал, включил загрузку сотрудников, без загрузки всех чатов зависания нет, так как чатов грузилось аж 45998. При этом, без чатов, запрос выполняется всё равно долго >7 секунд, но там есть кэширование, которое более менее выручает. В общем ждём исправлений.
Установил 28.07.2021 обновление, в том числе обновился и модуль календаря, сотрудники начали ругаться на неудобство, почему при планировании встречи убрали отображение отсутствий у участников встречи.
Сначала подумал что это новая фича, а потом решил проверить ))) Оказалось баг. В файле: /home/bitrix/www/bitrix/modules/calendar/classes/general/calendar_planner.php в строке 161, 162, 167 и 172 перепутаны имена ключей массива, и вместо DT_TO и DT_FROM, которые приходят из метода CCalendar::GetAccessibilityForUsers вписаны DATE_TO и DATE_FROM.
Решение
Нужно исправить имена ключей, или просто вставить в 160 строку перенос значений в нужные ключи:
Не так давно начали использовать открытые линии, и пришлось столкнуться с некоторыми неудобствами.
Инструкция WhatsApp Начали использование с подключения вотсап, и первое с чем столкнулся, с бесполезной инструкцией по настройке этого канала связи. Я был вынужден искать ответы на многие вопросы вне этой инструкции:
Нигде не написано, что требуется создать бизнес аккаунт в Facebook
Бизнес аккаунт требуется верифицировать, об этом соответственно тоже, хотя там есть подводный камень в виде за дизейбленой кнопки.
О том что необходимо предоставить права для твилио на управление вотсап в созданном бизнес аккаунте.
В общем нет описания что есть Тивилио, а это лишь провайдер, у которого до сих пор интеграция с вотсап в бетта версии, и есть много недочётов к интерфейсу администратора, например нет возможности создавать шаблоны сообщений с изображениями или видео, а только текст. Хотя это уже возможно в вотсап.
Нет предупреждения, что через вотсап не получится делать рассылки (этот функционал допиливать пришлось, использовал возможность подключения смс провайдера по rest, если кому интересно могу скинуть в подробностях как это сделать и какие там трудности ))) )
Ну и самое главное, стоило сделать сноску в начале инструкции, что при прямых руках вы можете с российским номером использовать оригинальный апи вотсап, со всеми его возможностями. Об этом узнаёшь как только открываешь доки по интеграции с вотсап на фейсбуке, но ты это делаешь уже когда нужно готовое решение здесь и сейчас, и нет времени на написание модуля.
В общем инструкция возможно просто давно не актуализировалась, хотя дата стоит 08 июня 2020.
im.bitrix.info Тут кстати отвечу и на вопрос о том, почему я не пишу в техподдержку Bitrix. Потребовалось 6 рабочих дней, что бы дождаться ответа от техподдержки что такое im.bitrix.info. И техподдержка не смогла объяснить что такое im.bitrix.info, и зачем он нужен, например коробке (ответ поражает информативностью):
Вопрос задал больше из интереса какой будет ответ, так как о функциях сервиса можно догадаться:
Для удобства обновления апи каналов, если что-то изменится в апи одного из каналов не потребуется выпускать обновление
Для упрощения подключения каналов использующих OAuth пользователями, не требуется создавать приложение в аккаунте сервиса
Для распределения нагрузки потока сообщений в облачные порталы
....
И вроде бы всё хорошо, если бы из-за этого сервиса не возникала задержка в получении сообщений с каналов, особенно было ощутимо в первый день (совпадение?) в середине дня сообщения приходили на портал с задержкой в 40 минут, и в доступности нашего портала не было проблемы, это подтверждало изменение веб-хука для входящих сообщений в сервисе твилио, направляешь напрямую на портал, сообщения доходят без задержки секунда в секунду. Ответ поддержки был из разряда "перезагрузите компьютер":
На следующий день вроде всё нормализовалось, но задержка осталась от 5 секунд, она присутствовала на всех каналах связи кроме виджета на сайт, что логично, ведь виджет работает напрямую с сервером. И обнаружилась другая проблема, некоторые сообщения не доходят до открытых линий. Уже рассчитывать на поддержку не стал полез в ядро, благо сделали возможность писать лог коннектора открытых линий, он помог найти причину:
Скрипт получения сообщения останавливался из-за выбрасываемого исключения =(! Выяснять причину почему файл терялся я не стал, полез сразу по пути где было получено исключение, и немного покопав вышел на базовый класс коннекторов, причиной всему было скачивание аватарки писавшего клиента, по каким-то причинам она не всегда скачивалась. Но это бы не беда, но никто не позаботился отлавливать это исключение, что бы доставка сообщения не прерывалась!
И это ещё не всё, эта ошибка привела меня к тому, что создаёт часть задержки в доставке сообщений. Аватарка скачивалась при каждом входящем сообщении! По крайней мере для VK точно. Всё дело в том, что для сравнения данных используется MD5 хэш массива данных о пользователе полученных из коннектора, кто лажал было не понятно. Решение было топорным, отключить в коде вообще обработку изображения из каналов, это уменьшило задержку в доставке сообщений, и исключило ошибку, когда сообщение не доходило.
Итого почему мне не нравится использование im.bitrix.info:
нестабильность, да я не уверен в стабильности сервисов Битрикс, даже этот портал для разработчиков периодически падает. Ну и никто не исключает что между моим порталом и сервисом на магистрали будет авария, и я лишусь открытых линий полностью, хотя сервера каналов будут в полне доступны.
централизованность, упал сервис, недоступны все каналы кроме виджета.
зависимость от других порталов, которые используют этот сервис, например мои сообщения могу просто встать в очередь, из за того что сервер не успевает их обработать.
задержка доставки сообщений, при работе сервиса в штатном режиме.
конфиденциальность, что происходит с сообщениями не известно.
Всё это можно описать одним словом - зависимость, это дополнительное звено в доставке сообщений, которое находится вне моей ответственности, я не могу повлиять на решение проблем с этим сервисом, только писать в поддержку и ждать, ждать, ждать
ПС Данные по ошибке возникающей со скачиванием аватара передал в поддержку 4 июня, и пока не получал комментарием, только вопрос "можно ли закрыть чат?"
Forest Martin, пишите в поддержку, я спустя несколько обновлений переключил снова на работу через сервер битрикса, сейчас работает вроде без сбоев тьфу тьфу тьфу.
! Главное помните что если вы не продлите вовремя лицензию битрикса, ваши открытые линии не будут работать, к сожалению эта информация не высвечивается в первых строчках лендингов компании Битрикс, которые завлекают клиентов, а спрятана она за несколькими ссылками в факе.
Очередное обновление не прошло гладко. При установке обновления очередного модуля выскочила ошибка 504. Это уже не первый раз происходит.
Причина такой ошибки - создание индексов, на довольно большом объеме данных. Из-за чего база может затянуть время выполнения скрипта больше чем таймаут nginx. В этот раз виновником был модуль voximplant, при обновлении он зарядил создание индекса CREATE FULLTEXT INDEX IXF_VI_STATS_1 ON b_voximplant_statistic_index(CONTENT)
Приходится через SHOW PROCESSLIST смотреть когда база справится с этим, и продолжать установку обновлений, в надежде что скрипт последней установки закончил выполнение корректно.
Почему нельзя вынести создание индексов на агенты, уже после установки обновления, не понятно.
Идеально было бы вынести установку обновлений в отдельный фоновый процесс на сервере, а не устанавливать их дергая сервер ajax запросами.
Надо петицию писать разработчикам битрикс, что бы сделали отложенное выполнение запросов при обновлении. Вчера вышло обновление, сегодня устанавливаю, снова долгие операции в БД, на этот раз изменение таблицы:facepalm: Одна из таких операций:
ALT ER TABLE b_crm_dp_entity_hash ADD DATE_MODIFY DATETIME DEFAULT CURRENT_TIMESTAMP NULL
У меня в этой таблице 3 220 865 записей, при всем уважении Сергей Рыжиков, вы когда эти операции вписываете в обновление, не предполагаете что может быть такая ситуация?
Вынесите эти операции в фон, или хотя бы перед выполнением проверяйте количество строк в таблице и выдавайте предупреждение человеку устанавливающему обновления, что эти операции лучше сделать вручную через консоль.
Именно в такой формулировке я получил инцидент, после последнего обновления. И да действительно при открытии профиля страница зависала и выпадала в ошибку 504 Gateway Timeout. Но было одно но, такое зависание происходило только при открытии профиля через глобальный поиск.
Причина
В отладчике Хрома был найден запрос на поиск задач, из-за выполнение которого всё и зависало. Одел HEV, взял монтировку и полез в модуль tasks.
Примечание. Очень был огорчён, что из настроек компонента search.title уже ничего не используется, другими словами на время решения проблемы отключить поиск по задачам можно было только закомментировав строки 951 и 952 в файле /bitrix/templates/bitrix24/components/bitrix/search.title/.default/script.js
Итак в tasks косячил метод CTask::GetList();, причём вис он наглухо игнорируя лимит на выполнение скрипта php, поэтому собственно всё адекватно обрывал nginx по таймауту. А происходило так, потому что php ждал ответа от MySQL из-за очень плохо построенного запроса, вот он:
Поясню, нельзя помещать в IN подзапросы, только фиксированные значения, иначе, таким образом вы обречёте мускл выполнять этот подзапрос для каждой проверяемой строки таблицы. В моей таблице b_tasks 85384 строки не удивительно, что запрос вышел далеко за пределы таймаута nginx в 5 минут.
Решение
Аккуратно, не задевая лишних строк, монтировочкой выцарапываем костыль с надеждой на следующее обновление, а именно:
В строке 6596 объявляем глобальную переменную $DB:
global $DB;
Строку 6605 (сверьтесь со скрином на всякий случай) заменяем на код, который произведёт запрос идентификаторов доступных для пользователя задач, и вставит их в оператор IN как фиксированные значения:
Такое решение сократило запрос который длился более 5 минут до 2,5 секунд, что терпимо.
А ещё...
Кому интересно, данный запрос производит поиск по задачам, а эти вредные подзапросы в IN не что иное как проверка прав на задачи. Поэтому данная ошибка проявляется у разных пользователей по разному (у кого-то её вообще нет, а у кого-то от подвисаний до выпадания в 504), так сказать в меру прав доступа сотрудника к задачам, ну и конечно же играет роль общее количество задач. Данная ошибка никогда не возникнет под учёткой администратора, так как ему в запрос не подставляется проверка прав, поэтому не торопитесь говорить пользователям: "Проблема на вашей стороне".
Наткнулся на несправедливость, в пылу разработки облачной версии, забывают про коробку. Так например забыли про вывод в фильтре полей типа hlblock, выводится оно в таком виде, и никак нельзя установить в нём значение:
Или так (в этом случае кстати можно хотя бы ID записи ввести для отбора):
Решение и причина проблемы просты, для элементов инфоблока адаптацию поля под ui сделали, а для HL нет, поэтому надо её доделать, пока это не появится в обновлении. Маскируемся под разработчика битрикс и лезем в код модуля crm:
/bitrix/modules/crm/lib/filter/userfielddataprovider.php В строке 145 добавляем тип hlblock в условие, что бы он определялся как список (list):
|| $typeID === 'hlblock'
Далее в этом же файле чуть ниже, в строке 261 (может отличаться смотрите ориентир), добавляем формирование списка значений:
Примечание. Обратите внимание, что в формировании списка стоит лимит на 500 записей, такой же лимит выставлен и для iblock_element, и для iblock_section. Это не есть хорошо, конечно же в идеале поле с большим количеством элементов, должно получать список элементов динамически с фильтрацией, но думаю и этого дождёмся.
Теперь поле выглядит как обычное поле списка с мультивыбором:
Однако это не всё, мне по этому полю нужно было отбирать участников рассылки в модуле CRM-Маркетинг. А там как оказалось поля формируются совсем другим методом. Поэтому открываем файл:
/bitrix/modules/crm/classes/general/crm_usertype.php В строке 338 вставляем код формирования поля с элементами списка:
Сегодня письмо пришло, с такой отметкой. Только проблем в том, что я во вторник обновился и эти методы уже на 06.10.2020 были изменены, и стали вызывать ошибку при их статическом методе. Спасибо за такой подробный своевременный чейнджлог команда битрикс.
Теперь только нужно использовать так:
global $USER;
$USER->GetID();
И даже в этой отметке информация не полная, помимо методов CUser::GetID() и CUser::IsAuthorized(), так же недоступными для статичного вызова стали следующие методы класса CUser:
Но это же не важно указывать , а ещё уважаемые разработчики битрикс, у вас в файле /login/index.php вашего готового решения современный Интернет-магазин есть вот такой кусок кода:
Надеюсь вы там его не забудите поправить и включить в обновление.
ПС Кто знает что в чейнджлогах скрывается за пунктами: - Незначительные исправления. - Незначительные изменения. , которые от версии к версии появляются, может быть очередное исправление, которое заставит перелопатить наш код.
Жуков Евгений написал: Я передавал автору модуля. Его ответ - так использовать некорректно.
Не понял, но пользовательское поле привязки к hlblock выводится в фильтре сегмента, и в нем нет возможности выбрать элементы hlblock по которым требуется фильтрация.
Жуков Евгений написал: Не ко мне вопрос. Создайте обращение в ТП.
Тут уж быстрее правку в код внести, чем проходить несколько уровней поддержки объясняя всё каждый раз, и в конечном итоге будет создан тикет в разработку, на который не будет ответа.
Что случилось: При экспорте диалогов открытых линий в эксель выдаёт вот такое исключение
Причина
Вся причина в очень интересном подходе подключения кастомных обработчиков ajax запросов.
Ошибка вызвана отсутствием имени модуля в переменной module класса обработчика /bitrix/components/bitrix/imopenlines.statistics.detail/ajax.php, открываем файл:
Переменная есть, так почему вылазит ошибка? Кто более внимательный, заметит, что в трассировке нет вообще класса ImOpenLinesStatisticsDetailAjaxController, но есть его предок Main\Controller\Export, так почему же обработку производит предок?
А потому что вот как в ядре подключаются классы обработки ajax: /bitrix/www/bitrix/modules/main/lib/engine/router.php:222
Такое решение по выявлению подключенных классов описано в комментариях к функции get_declared_classes() на php.net. И он бы работал не используя разработчики Битрикс автозагрузку классов spl_autoload_register(). В этом случае php подключает класс только после его использования, вот и получается, что в файле /bitrix/components/bitrix/imopenlines.statistics.detail/ajax.php порядок подключения классов такой:
[506] => CComponentEngine [507] => ImOpenLinesStatisticsDetailAjaxController - находится в файле /bitrix/components/bitrix/imopenlines.statistics.detail/ajax.php [508] => Bitrix\Main\Controller\Export - является предком ImOpenLinesStatisticsDetailAjaxController, и к нему обращаются первый раз [509] => Bitrix\Main\Engine\Controller - является предком Bitrix\Main\Controller\Export, и к нему обращаются первый раз
Далее в переборе этого списка проверяется Bitrix\Main\Controller\Export, который является наследником Bitrix\Main\Engine\Controller, и возвращается в качестве кастомного обработчика вместо класса ImOpenLinesStatisticsDetailAjaxController.
Вот такой вот примитивный баг, как он прошел тестировщиков я не представляю.
Решение Самое банальное решение, пока не выйдет обновление, сделать вызов Bitrix\Main\Controller\Export, где-нибудь в init.php,например:
class kostyliforever extends \Bitrix\Main\Controller\Export{}
Хотел обратить внимание на одну новую особенность пользовательских полей и работы с ними через ORM. Конкретно если создать множественное поле типа Строка, и вы полнить запрос с фильтром по нему:
$q = new \Bitrix\Main\Entity\Query(FAQArticleTable::getEntity());
$q->setSelect(['ID', 'UF_NAME'])
->setFilter(['UF_THEME' => ['MAIN'],]);
то мы получим такой запрос:
SEL ECT
`f_aq_article`.`ID` AS `ID`,
`f_aq_article`.`UF_NAME` AS `UF_NAME`
FR OM `b_faq` `f_aq_article`
WHERE (UPPER(`f_aq_article`.`UF_THEME`) like upper('MAIN'))
который не принесёт результата, так как данные в поле таблицы хранятся с использованием serialize:
Такой запрос стал формироваться в последнем обновлении, которое я установил 04.06.2020 До этого формировался запрос с использованием отдельной таблицы для значений множественного поля:
SELECT `f_aq_article`.`ID` AS `ID`,
`f_aq_article`.`UF_NAME` AS `UF_NAME`
FR OM `b_faq` `f_aq_article`
WH ERE `f_aq_article`.`ID` IN (SELECT
`f_aq_article_tmp880275262`.`ID` AS `ID`
FR OM `b_faq` `f_aq_article_tmp880275262`
LEFT JOIN `b_faq_uf_theme` `f_aq_article_f_aq_article_utm_uf_theme_object_tmp880275262` ON `f_aq_article_f_aq_article_utm_uf_theme_object_tmp880275262`.`ID` = `f_aq_article_tmp880275262`.`ID`
WH ERE (UPPER(`f_aq_article_f_aq_article_utm_uf_theme_object_tmp880275262`.`VALUE`) like upper('MAIN')))
Согласен запрос не ахти, и работает медленно, но об этом ниже.
Решение
Первое что приходит в голову, добавить в фильтр маску:
$q = new \Bitrix\Main\Entity\Query(FAQArticleTable::getEntity());
$q->setSelect(['ID', 'UF_NAME'])
->setFilter(['UF_THEME' => ['%MAIN%'],]);
и это работает, но есть две проблемы:
Менять это во всех местах использования множественных строк.
Но главная проблема - это получение не верных результатов, этот запрос отберёт все строки таблицы, в которых поле содержит заданную маску.
И это очень всё портит, раньше запрос работал без использования маски и отбирал только соответствующие значения. В итоге получается, что решением этой проблемы остаётся вынос значений в отдельный hlblock, и создания связи с ним, то есть то, что раньше делалось на уровне ядра. И это решение тянет за собой реализацию в интерфейсе заполнения множественных значений значений и запись этих значений в этот отдельный hlblock, а в элемент с которым он связан идентификаторов.
ПС А использование hlblock тоже проблематично, если у вас в нем несколько десятков тысяч строк, то открытие формы элемента у которого есть поле связанное с этим hlblockом вызовет долгий рендеринг страницы, а на слабом компьютере выскочит:
Столкнулись с аналогичной проблемой, только "Строки" кушает нормально, а вот "Привязка к элементам highload-блоков" поломались, причём даже в админке. И это не особенность, а здоровенный баг, который ломает сайты.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».