При разработке сложных решений с лихо закрученной бизнес логикой, которые появляются в результате dream-bruteforce-brainstorming(а) различных department-ов заказчика, нам, обычным разработчикам и админам, иногда приходится сталкиваться с такой вещью, как Apex CPU Time Limit.
- Согласно официальному ответу :
для того, чтобы не сталкиваться с Apex CPU Time Limit Exceeded в процессе работы, необходимо учитывать следующие моменты данного лимита:
-
Лимит включает в себя почти все, что происходит на сервере, включая декларативные действия и инструменты, работающие в рамках одного Apex контекста - т.е. для всего исполняемого Apex кода и любых процессов, которые вызываются из этого кода (напрямую или косвенно), таких как процессы валидации, workflow, process builder processes, flow и т.д.
-
Лимит является общим и для вашего кода, и для кода certified managed packages. Для многих других видов лимитов у managed packages есть свои отдельные лимиты, но этот - одно из исключений. Заветные ~10 сек вы все-таки делите с другими пакетами. И тут проблема не столько в самих пакетах, сколько в пользователях, которые могут установить неоправданно много этих самых пакетов, с точки зрения здравого смысла, логики и требуемой функциональности.
-
Лимит относится к разряду статичных. Т.е. нет никаких workaround(ов), позволяющих каким-то образом увеличить данный лимит, будь то настройки самой организации в Setup, покупка дополнительных лицензий или даже специальный тарифный план с увеличенным CPU Time на транзакцию.
-
Лимит немедленно и полностью останавливает выполнение в рамках контекста как только достигнуто превышение.
-
Лимит, его нарушение, осуществляет roll-back всех успешных DML операций в рамках контекста.
-
Лимит НЕ учитывает время “ожидания на выполнение” на уровне базы данных для DML, SOQL, SOSL и время ожидания Apex callouts.
- Как не получить Apex CPU Time Limit Exceeded.
-
Используйте встроенные возможности Apex и обращений к базе данных.
Вместо:
Наверное, лучше обойтись таким вариантом:
Т.е., по возможности, вынесите логику фильтрации записей, выполнения элементарных агрегирующих операций (SUM, AVG, COUNT) в сами запросы. -
Используйте асинхронные операции там, где это возможно с точки зрения интерфейса / бизнес-логики / архитектуры решения. Особенно для “долгих” и/или непредсказуемо долгих операций: например, отправка email / mass email, создание “вспомогательных” записей в виде кастомных related объектов - первые кандидаты на подобную оптимизацию.
-
Рассмотрите возможность переноса логики содержащейся в инструментах автоматизации на уровень триггеров. Причем весь код лучше поместить в helper класс, гарантирующий “одноразовый запуск”, независимо от того, что могут “начудить” с количеством вызовов триггеров в одном контексте установленные managed packages и/или legacy код из разряда “так исторически сложилось”.
-
Используйте возможности dev console при анализе возникшей ошибки, а именно в данном случае особенно полезную вкладку Timeline:
И главное, при получении Apex CPU Time Limit Exceeded:
Keep calm!