Регистрация  |  Вход

Тригер и лимиты: более сложные ситуации

Тригер и лимиты на Select и DML.
Эта тема много раз обсуждалась, прнцип один: накаких Select и DML в "основном" цикле тригера, и вообще в каких-либо циклах.
Решение в том, чтобы все требуемые данные (в т.ч. по связям) выквериваются одним махов, обрабатываются циклами, и вставляются одним махом.

Но столнкулся с простейшей ситуацией, которая вогнала меня в ступор (ну может для понедельника - это нормально).

в тригере в "основном цикле" идет вызов какого-то класса. Тот Класс отлично написан, один раз Кверит инфу, один раз ставляет: все по-фен-шую...

Но в тесте (и возможно в будущей реальной жизни), тригер к примеру примет 200 записей и двести раз сделает вызов класса, которые сделает слишком много обращений в БД...

Как выход вижу: класс должен принимать на вход не одну запись (ее АйДи), а массив, и дальше одним махом все кверить, запись за записью обрабатывать, и одним махов вставлять\апдатировать.

и в тригере тогда этот класс(или его стат метод) вызывается не в цикле, а только однажды.

Тогда норм.

Кстати у меня есть именно такой случай, но там в тригере вызыватся футур стат метод которые далает колаут. И, да, там мой класс принимает только одну запись. Но он пока в тесте не выпал по лимитам. Может потому, что у футур кола больше лимит, или я забросил в тесте мало записей.
Проверил: в тесте передаю в тригер, вызывающий футур стат метод с колаутом, 10 записей - все норм.
Передаю 15 записей - нет, тест не упал - но класс со стат методом перестал покрываться вовсе!!!
Да....

Продолжу тему в другом направлении.
Где-то читал, что желательно, чтобы на объекте был только один тригер.
Таким образом получается, что в этом единственном тригере весь функционал выносится в классы, а сам тригер предстваляется из себя только (дополняемый) набор условия делающих высовы соответсвующих классов (принимающих пачку записей - не по одной) и все!

[b]Тригер и лимиты на Select и DML.[/b] 
Эта тема много раз обсуждалась, прнцип один: накаких Select и DML в "основном" цикле тригера, и вообще в каких-либо циклах.
Решение в том, чтобы все требуемые данные (в т.ч. по связям) выквериваются одним махов, обрабатываются циклами, и вставляются одним махом.

Но столнкулся с простейшей ситуацией, которая вогнала меня в ступор (ну может для понедельника - это нормально).

в тригере в "основном цикле" идет вызов какого-то класса. Тот Класс отлично написан, один раз Кверит инфу, один раз ставляет: все по-фен-шую...

Но в тесте (и возможно в будущей реальной жизни), тригер к примеру примет 200 записей и двести раз сделает вызов класса, которые сделает слишком много обращений в БД...

[b]Как выход вижу: [/b]класс должен принимать на вход не одну запись (ее АйДи), а массив, и дальше одним махом все кверить, запись за записью обрабатывать, и одним махов вставлять\апдатировать. 

и в тригере тогда этот класс(или его стат метод) вызывается не в цикле, а только однажды.

Тогда норм. 

Кстати у меня есть именно такой случай, но там в тригере вызыватся футур стат метод которые далает колаут. И, да, там мой класс принимает только одну запись. Но он пока в тесте не выпал по лимитам. Может потому, что у футур кола больше лимит, или я забросил в тесте мало записей.
Проверил: в тесте передаю в тригер, вызывающий футур стат метод с колаутом, 10 записей - все норм.
Передаю 15 записей - нет, тест не упал - но класс со стат методом перестал покрываться вовсе!!!
Да....

Продолжу тему в другом направлении.
Где-то читал, что желательно, чтобы на объекте был только один тригер.
Таким образом получается, что в этом [b]единственном тригере[/b] весь функционал выносится в классы, а сам тригер предстваляется из себя только (дополняемый) [b]набор условия делающих высовы соответсвующих классов[/b] (принимающих пачку записей - не по одной) и все!

Den Brown
Как выход вижу: класс должен принимать на вход не одну запись (ее АйДи), а массив, и дальше одним махом все кверить, запись за записью обрабатывать, и одним махов вставлять\апдатировать.

!!! именно так. В точку! Best Practice: Bulkify Your Code.
Любой метод должен предусматривать что его могут вызвать со списком параметров. А передать в списке 1 элемент всегда можно.

Den Brown
Продолжу тему в другом направлении.
Где-то читал, что желательно, чтобы на объекте был только один тригер.
Таким образом получается, что в этом единственном тригере весь функционал выносится в классы, а сам тригер предстваляется из себя только (дополняемый) набор условия делающих высовы соответсвующих классов (принимающих пачку записей - не по одной) и все!

Тоже все правильно. Лучше 1 триггер на объекте, а логика вынесена в service layer. - это уже высшее программирование - паттерны проектирования. Очень сильно помогает структурировать код и избавиться от повторов.

[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/

Ночью думал, и кажется понял, почему у меня в тесте "выключаются" из работы футур классы, если вызывать их более 10 раз. Там колауты.

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 подумать?