Есть ли правильный способ гарантировать, что только один пользователь одновременно вносит изменения в объект с REST + HTTP? - PullRequest
3 голосов
/ 10 января 2012

Я создал приложение Django / Tastypie, в котором несколько человек могли одновременно изменять атрибуты строки в базе данных или, возможно, PUT-данные, которые устарели.

Например:

 # the Django model
 class Thing(models.Model):
      name = models.CharField(max_length=100)
      description = models.TextField()

 # the Tastypie Resource
 class ThingResource(ModelResource):
       class Meta:
           queryset = Thing.objects.all()

Теперь предположим, что любое количество пользователей может изменить name или description Thing в любой момент времени. Они могут сделать это одновременно или кто-то может надолго оставить приложение открытым, а затем вернуться и изменить его.

Чего я пытаюсь избежать, так это скрытых неверных изменений. Учитывая следующую ситуацию:

#1 User 1: Opens app viewing Thing #1 with name = "my name", description = "my description"
#2 User 2: Opens app viewing Thing #1 (same state as User 1)
#3 User 2: Changes description of Thing #1 to "something"
#4 User 1: Changes name of Thing #1 to "some other name"

После строки #4 состояние Thing # 1 должно быть name = "some other name", description = "something" вместо name = "some other name", description = "my description".

Если приложение не знает (в режиме реального времени или посредством регулярного обновления данных на странице) заранее, что объект на сервере изменился, как можно предотвратить эту ситуацию?

Я рассмотрел добавление поля sequence = models.PositiveIntegerField(), в котором я увеличиваю его каждый раз, когда производится обновление, и поэтому я могу определить, устарел ли объект, когда происходит обновление, но так ли это лучше? Есть ли способ лучше? Кажется, это будет обычная модель, верно?

Ответы [ 2 ]

4 голосов
/ 10 января 2012

При использовании REST состояние ресурсов управляется сервером, поэтому ваша идея о поле последовательности является точной. Сервер отслеживает, в какой версии находится ресурс, и клиент сообщает, какую версию, по его мнению, он создает при отправке новой версии. Если клиент ошибается, сервер сообщает об этом.

предложение Яна об ETag или модифицированных датах звучит как правильный способ сделать это, и этот ответ на аналогичный вопрос соглашается. Я на самом деле не очень много опыта этого.

3 голосов
/ 10 января 2012

RESTful способ сделать это состоит в том, чтобы клиент отслеживал либо заголовок Last-Modified, либо заголовок Etag, возвращаемый с ресурсом. Затем, когда он POSTs, добавить заголовок, как

If-Unmodified-Since: <date-noted-from-initial-GET>

или

If-Match: <etag-noted-from-initial-GET>

Если ресурс был изменен на сервере с момента его первоначальной загрузки клиентом, сервер должен вернуть ответ «Сбой предусловия». Затем клиент может извлечь текущую версию и отобразить что-то полезное для пользователя.

Получить вкусный пирог, чтобы ответить на эти заголовки, может быть немного сложнее.

...