Немного сложно понять, был ли второй вызов от того же клиента с тем же токеном запроса или от другого клиента.
Обычно в случае одновременных запросов от разных клиентов, работающих с одним и тем же ресурсом, вы также хотели бы реализовать стратегию управления версиями вместе с токеном запроса для идемпотентности.
Типичной стратегией версий в реляционной базе данных может быть столбец версии с триггером, который автоматически увеличивает число при каждом обновлении записи.
При этом все клиенты должны указать свой токен запроса, а также версию, которую они обновляют (обычно для этого используется заголовок IfMatch, а номер версии используется в качестве значения ETag).
На стороне сервера, когда приходит время обновить состояние ресурса, вы сначала проверяете, соответствует ли номер версии в базе данных версии, предоставленной в ETag. Если они это сделают, вы записываете изменения, и версия увеличивается. Если предположить, что второй запрос работает с тем же номером версии, что и первый, он затем завершится с ошибкой 412 (или 409, в зависимости от того, как вы интерпретируете спецификации HTTP), и клиент не должен повторять попытку.
Если вы действительно хотите немедленно остановить второй запрос, пока выполняется первый запрос, вы идете по пути пессимистической блокировки, которая не очень подходит для REST API.
В случае, когда вы на самом деле говорите о повторной попытке клиента с тем же токеном запроса, потому что он получил временную сетевую ошибку, это почти тот же случай.
Оба запроса будут выполняться одновременно, второй запрос запустится, потому что первый запрос еще не завершен и еще не записал токен запроса в базу данных, но тот из них, который завершится первым, завершится успешно и запишет токен запроса.
Для другого запроса он получит конфликт версий (поскольку первый запрос увеличил версию), после чего он должен перепроверить таблицу базы данных токенов запроса, найти там свой собственный токен и предположить, что это был параллельный запрос, который завершился до он сделал и вернул 200.
Кажется, что это много, но если вы хотите охватить все странные и замечательные режимы отказа при работе с REST, идемпотентностью и параллелизмом, это способ справиться с этим.
person
nrjohnstone
schedule
22.08.2017