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

Заблокировать запись до вызова внешнего сервиса

Есть страничка. Кнопка. Нажимаем кнопку, собираются данные, отправляется запрос на внешнюю систему, приходит ответ, сохраняем ответ в СФ.
Если же открыть эту страничку в двух разных местах и почти одновременно нажать эту кнопку, то запрос отправится два раза и запись тоже два раза обновится.

Вопрос:

Можно ли как-то ДО вызова внешнего сервиса заблокировать запись или еще какой флаг поставить, что б хотя бы запись по два раза по два раза не обновлялась не обновлялась? Блокировать, а птм разблокировать ее только в одном потоке.

Есть страничка. Кнопка. Нажимаем кнопку, собираются данные, отправляется запрос на внешнюю систему, приходит ответ, сохраняем ответ в СФ.
Если же открыть эту страничку в двух разных местах и почти одновременно нажать эту кнопку, то запрос отправится два раза и запись тоже два раза обновится.

Вопрос:

Можно ли как-то ДО вызова внешнего сервиса заблокировать запись или еще какой флаг поставить, что б хотя бы запись по два раза по два раза не обновлялась не обновлялась? Блокировать, а птм разблокировать ее только в одном потоке.
Оно
[url=https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_locking_statements.htm]Locking Statements[/url]
?

Andrii Muzychuk
Оно
Locking Statements
?

В этом случае все равно будет 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 попробую.

wilder
В этом случае все равно будет 2 посылки на внешний сервис, ну или ловить exception и обрабатывать его. И опять же ворос из какого потока данные более правильные?
А я не знаю из какого потока они будут правильными. Сервис создал две записи у себя и когда пользователь вычитывает запись, то их две вместо одной. Это мы поправили. Но осталась проблема на стороне СФ. Из-за двух вызовов сначала запись сохраняется правильно, а на второй раз выполняется другая логика и получается чушь.

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]А я не знаю из какого потока они будут правильными. Сервис создал две записи у себя и когда пользователь вычитывает запись, то их две вместо одной. Это мы поправили. Но осталась проблема на стороне СФ. Из-за двух вызовов сначала запись сохраняется правильно, а на второй раз выполняется другая логика и получается чушь.

Andrii Muzychuk
O! Ща Set Approval Process Locks and Unlocks with Apex Code попробую.

wilder
В этом случае все равно будет 2 посылки на внешний сервис, ну или ловить exception и обрабатывать его. И опять же ворос из какого потока данные более правильные?
А я не знаю из какого потока они будут правильными. Сервис создал две записи у себя и когда пользователь вычитывает запись, то их две вместо одной. Это мы поправили. Но осталась проблема на стороне СФ. Из-за двух вызовов сначала запись сохраняется правильно, а на второй раз выполняется другая логика и получается чушь.

Можно попробовать использовать ключи для доступа к внешнему сервису. Он уже и проверяет что делать с дублями.

[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);

вызывает
FATAL_ERROR|System.UnexpectedException: null

:-(

Хм...
Код
[code]Approval.LockResult lr = System.Approval.lock(record);[/code]
вызывает
[quote]FATAL_ERROR|System.UnexpectedException: null[/quote]
:-(

Следующая конструкция должна вроде как отработать:
1. Завести на объекте поле куда будешь складывать либо дату последней отправки на внешний сервис, либо просто флажок отправки
2. Запрашивая запись из базы вычитывать это поле и использовать

FOR UPDATE

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."

Следующая конструкция должна вроде как отработать:
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 свалится? Как снять блокировку с записи?

Как только транзакция которая её залочила закончится. Это ответ сразу на все вопросы :)

Как только транзакция которая её залочила закончится. Это ответ сразу на все вопросы :)