2016-06-29 11 views
0

Я разрабатываю веб-службу для регулярного получения обновлений списков. На данный момент список все еще может быть смоделирован как единый объект (/lists/myList) или фактическая коллекция со многими ресурсами (/lists/myList/entries/<ID>). Списки большие (миллионы записей), а обновления небольшие (часто менее 10 изменений).HTTP ReST: обновление больших коллекций: лучший подход, чем JSON PATCH?

Клиент получает URL-адреса службы веб и списки для распространения, например:

Затем он будет настраивать списки и обновления. Вероятно, но не определено, есть ли какая-либо база данных за URL-адресами веб-службы.

Я занимаюсь исследованием, и, кажется, HTTP PATCH с использованием формата патча JSON - лучший подход.

Контекст и примеры: Каждый список имеет идентифицирующее имя, приоритет и миллионы записей. Каждая запись имеет идентификатор (определяется клиентом) и несколько необязательных атрибутов. Пример, чтобы создать список «requiredItems» с приоритетом 1 и два списка записей:

PUT /lists/requiredItems 
Content-Type: application/json 


{ 
    "priority": 1, 
    "entries": { 
    "1": { 
     "color": "red", 
     "validUntil": "2016-06-29T08:45:00Z" 
    }, 
    "2": { 
     "country": "US" 
    } 
    } 
} 

Для обновлений, клиент в первую очередь необходимо знать, что список выглядит сейчас на сервере. Для этого я бы добавил свойство «ревизия» в объект списка.

Тогда, я бы запросить этот атрибут:

GET /lists/requiredItems?property=revision 

Тогда клиент будет видеть, что необходимо изменить между пересмотром на сервере и последнюю версию известного клиента и составить JSON патч. Пример:

PATCH /list/requiredItems 
Content-Type: application/json-patch+json 

[ 
    { "op": "test", "path": "revision", "value": 3 }, 
    { "op": "add", "path": "entries/3", "value": { "color": "blue" } }, 
    { "op": "remove", "path": "entries/1" }, 
    { "op": "remove", "path": "entries/2/country" }, 
    { "op": "add", "path": "entries/2/color", "value": "green" }, 
    { "op": "replace", "path": "revision", "value": 10 } 
] 

Вопросы:

  • Этот подход имеет недостаток, заключающийся в несколько меньшей поддержки клиентов в связи с не-часто используется HTTP-глагола пластыря. Существует ли более совместимый подход, не жертвуя поддержкой HTTP (idempotency et cetera)?
  • Моделирование отдельных записей списка в виде отдельных ресурсов и использования PUT и DELETE (возможно, с ETag и/или If-Match) представляется вариант (PUT /lists/requiredItems/entries/3, DELETE /lists/requiredItems/entries/1PUT /lists/requiredItems/revision), но как бы я убедиться, что все эти операции применяются, когда сетевые капли в середине цепочки обновлений? Может ли HTTP PATCH работать с несколькими ресурсами?
  • Есть ли лучший способ «версии» списков, возможно, неявно также улучшить их обновление? Обратите внимание, что клиент определяет номер версии.
  • Правильно ли запрашивать номер версии с GET /lists/requiredItems?property=revision? Должен ли он быть отдельным ресурсом, например /lists/requiredItems/revision? Если это должен быть отдельный ресурс, как бы я его физически обновить (т. Е. Список и ревизия обновлены или оба не обновляются)?
  • Будет ли он работать в патче JSON, чтобы сначала проверить значение версии 3, а затем обновить его до 10 в том же патче?
+0

Пожалуйста, не спрашивайте более одного вопроса за раз. Все они действительны, но вы, вероятно, не получите ответа на все из них. –

+0

@ LutzHorn: спасибо. Ты прав. Должен ли я удалить все, кроме одного вопроса, и переставить остальные отдельно? Вводная часть будет такой же ... –

ответ

2

Этот подход имеет тот недостаток, что немного меньше поддержки клиентов в связи с не-часто используется HTTP глагола PATCH.

Насколько я могу судить, PATCH действительно только в том случае, Ваш сервер действует как немой документ магазин, где действие буквально «необходимо обновить вашу копию документа в соответствии со следующим описанием».

Итак, если ваш ресурс действительно является документом JSON, который описывает список с миллионами записей, тогда JSON-Patch - отличный ответ.

Но если вы ожидаете, что патч, как побочный эффект, обновит объект в вашем домене, тогда я подозрюю.

Является ли HTTP PATCH разрешенным для работы с несколькими ресурсами?

RFC 5789

Метод PATCH влияет на ресурс, определенный в Request-URI, и он также может иметь побочные эффекты на другие ресурсы

Я не заинтересован в запрашивая номер ревизии; у него, похоже, нет явного преимущества перед использованием подхода ETag/If-Match. Некоторые очевидные недостатки - кэши между вами и клиентом не знают, что список и номер версии связаны; кеш с радостью сообщит клиенту, что версия 12 списка - версия 7, или наоборот.

+0

Спасибо! Веб-служба может иметь или не иметь базы данных; Я разрабатываю клиент и веб-сервис, но не сервер. На стороне сервера будет несколько различных сторонних реализаций. Я добавил некоторые разъяснения в начале вопроса. –

+0

Я не понимаю, как HTTP надеется включить кеширование, если PATCH to/service/list1 может влиять на любой другой ресурс. Просто недействительно весь кеш при каждом запросе PATCH? –

+0

Справедливости ради PATCH, те же проблемы возникают с POST, PUT, DELETE. Когерентность кеша является одной из двух трудных проблем. – VoiceOfUnreason

0

Отвечая на мой вопрос. Мое первое поле может быть основано на мнениях, и, как уже указывалось, я задал много вопросов в одном сообщении. Тем не менее, вот резюме того, на что ответили другие (VoiceOfUnreason), и мои собственные дополнительные исследования:

ETags - это хеш-ресурс ресурсов HTTP. Их можно комбинировать с заголовками If-Match, чтобы иметь систему управления версиями. Однако заголовки ETag обычно не используются для объявления ETag ресурса, который создается (PUT) или обновленного (POST/PATCH). Сервер, хранящий ресурс, обычно определяет ETag. Я не нашел ничего явно запрещающего это, но многие реализации могут предполагать, что сервер определяет ETag и путается, когда он снабжен PUT или PATCH.

Отдельный ресурс редакции является действующей альтернативой ETags для управления версиями. Этот ресурс должен быть обновлен одновременно с ресурсом, который является пересмотром.

Не имеет смысла на уровне HTTP, чтобы иметь транзакции фиксации/откат, если только не моделирование самой транзакции как ресурса ReST, что усложнит ситуацию.

Однако некоторые свойства пластыря позволяют использовать его для этого:

  • HTTP-PATCH должен быть атомарным и может работать на нескольких ресурсах.RFC 5789:
    • Сервер должен применить весь набор изменений атомарны и никогда не обеспечивает (например, в ответ на GET во время этой операции) частично модифицированного представления. Если весь файл патча не может быть успешно применен, сервер НЕ ДОЛЖЕН применять какие-либо изменения.
    • Метод PATCH влияет на ресурс, идентифицируемый Request-URI, и также может иметь побочные эффекты для других ресурсов; то есть новые ресурсы могут быть созданы или уже модифицированы приложением PATCH. PATCH не является ни безопасным, ни идемпотентная
  • JSON PATCH может состоять из нескольких операций на нескольких ресурсах и все они должны быть применены или нет, должны быть применены, что делает его неявной транзакции. RFC 6902:
    Операции применяются последовательно в порядке их появления в массиве.

Таким образом, ревизия может быть смоделирована как отдельный ресурс и все еще обновляться в одно и то же время. Запрос текущей версии - это просто GET. Перенос транзакции - это один запрос PATCH, содержащий сначала проверку ревизии, затем операции над ресурсами (ресурсами) и, наконец, операцию обновления ресурса ревизии.

Сервер все еще может опубликовать версию как ETag основного ресурса.