Тригер и лимиты на Select и DML.
Эта тема много раз обсуждалась, прнцип один: накаких Select и DML в "основном" цикле тригера, и вообще в каких-либо циклах.
Решение в том, чтобы все требуемые данные (в т.ч. по связям) выквериваются одним махов, обрабатываются циклами, и вставляются одним махом.
Но столнкулся с простейшей ситуацией, которая вогнала меня в ступор (ну может для понедельника - это нормально).
в тригере в "основном цикле" идет вызов какого-то класса. Тот Класс отлично написан, один раз Кверит инфу, один раз ставляет: все по-фен-шую...
Но в тесте (и возможно в будущей реальной жизни), тригер к примеру примет 200 записей и двести раз сделает вызов класса, которые сделает слишком много обращений в БД...
Как выход вижу: класс должен принимать на вход не одну запись (ее АйДи), а массив, и дальше одним махом все кверить, запись за записью обрабатывать, и одним махов вставлять\апдатировать.
и в тригере тогда этот класс(или его стат метод) вызывается не в цикле, а только однажды.
Тогда норм.
Кстати у меня есть именно такой случай, но там в тригере вызыватся футур стат метод которые далает колаут. И, да, там мой класс принимает только одну запись. Но он пока в тесте не выпал по лимитам. Может потому, что у футур кола больше лимит, или я забросил в тесте мало записей.
Проверил: в тесте передаю в тригер, вызывающий футур стат метод с колаутом, 10 записей - все норм.
Передаю 15 записей - нет, тест не упал - но класс со стат методом перестал покрываться вовсе!!!
Да....
Продолжу тему в другом направлении.
Где-то читал, что желательно, чтобы на объекте был только один тригер.
Таким образом получается, что в этом единственном тригере весь функционал выносится в классы, а сам тригер предстваляется из себя только (дополняемый) набор условия делающих высовы соответсвующих классов (принимающих пачку записей - не по одной) и все!
[b]Тригер и лимиты на Select и DML.[/b] Эта тема много раз обсуждалась, прнцип один: накаких Select и DML в "основном" цикле тригера, и вообще в каких-либо циклах. Решение в том, чтобы все требуемые данные (в т.ч. по связям) выквериваются одним махов, обрабатываются циклами, и вставляются одним махом. Но столнкулся с простейшей ситуацией, которая вогнала меня в ступор (ну может для понедельника - это нормально). в тригере в "основном цикле" идет вызов какого-то класса. Тот Класс отлично написан, один раз Кверит инфу, один раз ставляет: все по-фен-шую... Но в тесте (и возможно в будущей реальной жизни), тригер к примеру примет 200 записей и двести раз сделает вызов класса, которые сделает слишком много обращений в БД... [b]Как выход вижу: [/b]класс должен принимать на вход не одну запись (ее АйДи), а массив, и дальше одним махом все кверить, запись за записью обрабатывать, и одним махов вставлять\апдатировать. и в тригере тогда этот класс(или его стат метод) вызывается не в цикле, а только однажды. Тогда норм. Кстати у меня есть именно такой случай, но там в тригере вызыватся футур стат метод которые далает колаут. И, да, там мой класс принимает только одну запись. Но он пока в тесте не выпал по лимитам. Может потому, что у футур кола больше лимит, или я забросил в тесте мало записей. Проверил: в тесте передаю в тригер, вызывающий футур стат метод с колаутом, 10 записей - все норм. Передаю 15 записей - нет, тест не упал - но класс со стат методом перестал покрываться вовсе!!! Да.... Продолжу тему в другом направлении. Где-то читал, что желательно, чтобы на объекте был только один тригер. Таким образом получается, что в этом [b]единственном тригере[/b] весь функционал выносится в классы, а сам тригер предстваляется из себя только (дополняемый) [b]набор условия делающих высовы соответсвующих классов[/b] (принимающих пачку записей - не по одной) и все!
[quote="Den Brown"]Как выход вижу: класс должен принимать на вход не одну запись (ее АйДи), а массив, и дальше одним махом все кверить, запись за записью обрабатывать, и одним махов вставлять\апдатировать. [/quote] !!! именно так. В точку! Best Practice: Bulkify Your Code. Любой метод должен предусматривать что его могут вызвать со списком параметров. А передать в списке 1 элемент всегда можно. [quote="Den Brown"]Продолжу тему в другом направлении. Где-то читал, что желательно, чтобы на объекте был только один тригер. Таким образом получается, что в этом единственном тригере весь функционал выносится в классы, а сам тригер предстваляется из себя только (дополняемый) набор условия делающих высовы соответсвующих классов (принимающих пачку записей - не по одной) и все![/quote] Тоже все правильно. Лучше 1 триггер на объекте, а логика вынесена в service layer. - это уже высшее программирование - паттерны проектирования. Очень сильно помогает структурировать код и избавиться от повторов.
Получается, что в крупном проекте, на ключевом(ых) объектах должен стоять один тригер.
При этом этот тригер - это просто коммутатор, "перекресток" бизнес-процессов: пришла в тригер такая-то ситуация - иди туда (вызывается какой-то класс), пришла другая - иди во туда (вызывается другой класс). Никакими операциями "по-существу" возникщего бизнес-процесса тригер не захламляется.
Ночью думал, и кажется понял, почему у меня в тесте "выключаются" из работы футур классы, если вызывать их более 10 раз. Там колауты. Может просто превышаю лимиты по ним. Но есть вопросы:
- Каждый запущенный асинхронный процесс имеет собсвенные лимиты или общие с материнским процессом?
- Каждый запущенный асинхронный процесс имеет собсвенные лимиты или общие с последующими отпочковавшимися от материнского процесса асинхронными процессами (точнее наоборот - вновь отпочковавшиеся процессынаследуют старые общие лимиты)?
- Асинронные процессы имеют бОльшие лимиты, но все равно только 10 колаутов на всех-про-всех?
если на все эти вопросы ответом будет "да", то мои класс выпадает из теста по превышению лимита по колаутам. В таком случае тестировать тот тригер можно максимально с 10 записями. Более того, даже делать его устойчивым к операциям с многочисленными записями (как мы описали выше) нет смысла - тригер (точнее футур класс в нем) никогда не упадет по ДМЛ и селектам, так как гораздо раньше он упадет по колаутам. Так получается?
Получается, что в крупном проекте, на ключевом(ых) объектах должен стоять один тригер. При этом этот тригер - это просто коммутатор, "перекресток" бизнес-процессов: пришла в тригер такая-то ситуация - иди туда (вызывается какой-то класс), пришла другая - иди во туда (вызывается другой класс). Никакими операциями "по-существу" возникщего бизнес-процесса тригер не захламляется. Ночью думал, и кажется понял, почему у меня в тесте "выключаются" из работы футур классы, если вызывать их более 10 раз. Там колауты. Может просто превышаю лимиты по ним. Но есть вопросы: - Каждый запущенный асинхронный процесс имеет собсвенные лимиты или общие с материнским процессом? - Каждый запущенный асинхронный процесс имеет собсвенные лимиты или общие с последующими отпочковавшимися от материнского процесса асинхронными процессами (точнее наоборот - вновь отпочковавшиеся процессынаследуют старые общие лимиты)? - Асинронные процессы имеют бОльшие лимиты, но все равно только 10 колаутов на всех-про-всех? если на все эти вопросы ответом будет "да", то мои класс выпадает из теста по превышению лимита по колаутам. В таком случае тестировать тот тригер можно максимально с 10 записями. Более того, даже делать его устойчивым к операциям с многочисленными записями (как мы описали выше) нет смысла - тригер (точнее футур класс в нем) никогда не упадет по ДМЛ и селектам, так как гораздо раньше он упадет по колаутам. Так получается?
Проверить почему падают future методы если не ошибаюсь можно в разделе Apex Job, там где находится список batch. Там показываются ошибки если они возникли в твоем future методе. Если только ты их не перехватываешь в try catch.
Каждый future метод это свой отдельный процесс со своими лимитами. Они между собой не зависят, как и не связаны с материнским процессом. Другое дело что с future методами тоже перебарщивать нельзя. Тут я писал про лимиты http://salesforce-developer.ru/novyiy-podhod-k-raschetu-limitov-dlya-asinhronnyih-protsessov-daily-asynchronous-limit/
Total number of methods with the future annotation allowed per Apex invocation - 10
Understanding Execution Governors and Limits
Если тебе надо вызывать так много future методов может стоит про batch подумать?
Проверить почему падают future методы если не ошибаюсь можно в разделе Apex Job, там где находится список batch. Там показываются ошибки если они возникли в твоем future методе. Если только ты их не перехватываешь в try catch. Каждый future метод это свой отдельный процесс со своими лимитами. Они между собой не зависят, как и не связаны с материнским процессом. Другое дело что с future методами тоже перебарщивать нельзя. Тут я писал про лимиты [url]http://salesforce-developer.ru/novyiy-podhod-k-raschetu-limitov-dlya-asinhronnyih-protsessov-daily-asynchronous-limit/[/url] [quote]Ночью думал, и кажется понял, почему у меня в тесте "выключаются" из работы футур классы, если вызывать их более 10 раз. Там колауты. [/quote] Total number of methods with the future annotation allowed per Apex invocation - 10 [url=https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_annotation_future.htm]Understanding Execution Governors and Limits[/url] Если тебе надо вызывать так много future методов может стоит про batch подумать?