Есть страничка. Кнопка. Нажимаем кнопку, собираются данные, отправляется запрос на внешнюю систему, приходит ответ, сохраняем ответ в СФ.
Если же открыть эту страничку в двух разных местах и почти одновременно нажать эту кнопку, то запрос отправится два раза и запись тоже два раза обновится.
Вопрос:
Можно ли как-то ДО вызова внешнего сервиса заблокировать запись или еще какой флаг поставить, что б хотя бы запись по два раза по два раза не обновлялась не обновлялась? Блокировать, а птм разблокировать ее только в одном потоке.
Есть страничка. Кнопка. Нажимаем кнопку, собираются данные, отправляется запрос на внешнюю систему, приходит ответ, сохраняем ответ в СФ. Если же открыть эту страничку в двух разных местах и почти одновременно нажать эту кнопку, то запрос отправится два раза и запись тоже два раза обновится. Вопрос: Можно ли как-то ДО вызова внешнего сервиса заблокировать запись или еще какой флаг поставить, что б хотя бы запись по два раза по два раза не обновлялась не обновлялась? Блокировать, а птм разблокировать ее только в одном потоке.
Оно [url=https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_locking_statements.htm]Locking Statements[/url] ?
В этом случае все равно будет 2 посылки на внешний сервис, ну или ловить exception и обрабатывать его. И опять же ворос из какого потока данные более правильные?
[quote="Andrii Muzychuk"]Оно [url=https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_locking_statements.htm]Locking Statements[/url] ?[/quote] В этом случае все равно будет 2 посылки на внешний сервис, ну или ловить exception и обрабатывать его. И опять же ворос из какого потока данные более правильные?
O! Ща Set Approval Process Locks and Unlocks with Apex Code попробую.
O! Ща [url=http://releasenotes.docs.salesforce.com/en-us/winter16/release-notes/rn_apex_approval_locks_unlocks.htm#rn_apex_approval_locks_unlocks]Set Approval Process Locks and Unlocks with Apex Code[/url] попробую. [quote="wilder"]В этом случае все равно будет 2 посылки на внешний сервис, ну или ловить exception и обрабатывать его. И опять же ворос из какого потока данные более правильные?[/quote]А я не знаю из какого потока они будут правильными. Сервис создал две записи у себя и когда пользователь вычитывает запись, то их две вместо одной. Это мы поправили. Но осталась проблема на стороне СФ. Из-за двух вызовов сначала запись сохраняется правильно, а на второй раз выполняется другая логика и получается чушь.
Можно попробовать использовать ключи для доступа к внешнему сервису. Он уже и проверяет что делать с дублями.
[quote="Andrii Muzychuk"]O! Ща [url=http://releasenotes.docs.salesforce.com/en-us/winter16/release-notes/rn_apex_approval_locks_unlocks.htm#rn_apex_approval_locks_unlocks]Set Approval Process Locks and Unlocks with Apex Code[/url] попробую. [quote="wilder"]В этом случае все равно будет 2 посылки на внешний сервис, ну или ловить exception и обрабатывать его. И опять же ворос из какого потока данные более правильные?[/quote]А я не знаю из какого потока они будут правильными. Сервис создал две записи у себя и когда пользователь вычитывает запись, то их две вместо одной. Это мы поправили. Но осталась проблема на стороне СФ. Из-за двух вызовов сначала запись сохраняется правильно, а на второй раз выполняется другая логика и получается чушь.[/quote] Можно попробовать использовать ключи для доступа к внешнему сервису. Он уже и проверяет что делать с дублями.
Хм...
Код
Approval.LockResult lr = System.Approval.lock(record);
Хм... Код [code]Approval.LockResult lr = System.Approval.lock(record);[/code] вызывает [quote]FATAL_ERROR|System.UnexpectedException: null[/quote] :-(
Следующая конструкция должна вроде как отработать:
1. Завести на объекте поле куда будешь складывать либо дату последней отправки на внешний сервис, либо просто флажок отправки
2. Запрашивая запись из базы вычитывать это поле и использовать
FOR UPDATE
PS: На вскидку не помню будет ли Http Callout Exception из-за того что запрос будет с FOR UPDATE. Т.к. запрос может обрабатываться до 120 секунд, параллельный поток не сможет так долго ждать и может отвалиться с чем-то вроде UNABLE TO GET EXCLUSIVE ACCESS ON ROW, или как-то так, так что это надо учесть и обрабатывать соответсвующим образом, вроде сообщения "Current record has been upated by another person, please wait and try again later."
Следующая конструкция должна вроде как отработать: 1. Завести на объекте поле куда будешь складывать либо дату последней отправки на внешний сервис, либо просто флажок отправки 2. Запрашивая запись из базы вычитывать это поле и использовать [code]FOR UPDATE[/code] 3. Проверить значение в поле из пункта 1 4. Отправить запрос 5. Получить ответ и обновить запись, в том числе поле из пункта 1 PS: На вскидку не помню будет ли Http Callout Exception из-за того что запрос будет с FOR UPDATE. Т.к. запрос может обрабатываться до 120 секунд, параллельный поток не сможет так долго ждать и может отвалиться с чем-то вроде UNABLE TO GET EXCLUSIVE ACCESS ON ROW, или как-то так, так что это надо учесть и обрабатывать соответсвующим образом, вроде сообщения "Current record has been upated by another person, please wait and try again later."
А через сколько или когда снимится блокировка этой записи? Если код после FOR UPDATE свалится? Как снять блокировку с записи?
А через сколько или когда снимится блокировка этой записи? Если код после FOR UPDATE свалится? Как снять блокировку с записи?
Как только транзакция которая её залочила закончится. Это ответ сразу на все вопросы :)
Как только транзакция которая её залочила закончится. Это ответ сразу на все вопросы :)