Я разрабатываю веб-службу для регулярного получения обновлений списков. На этом этапе список все еще можно смоделировать как единую сущность (/lists/myList
) или фактическую коллекцию с множеством ресурсов (/lists/myList/entries/<ID>
). Списки большие (миллионы записей), а обновления небольшие (часто менее 10 изменений).
Клиент получит URL-адреса и списки веб-служб для распространения, например:
- http://hostA/service/lists: список1, список2
- http://hostB/service/lists: список2, список3
- http://hostC/service/lists: список1, список3
Затем он будет отправлять списки и обновления в соответствии с настройками. Вероятно, но неизвестно, существует ли какая-то база данных за 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-команды PATCH. Существует ли более совместимый подход без ущерба для совместимости с HTTP (идемпотентность и так далее)?
- Моделирование отдельных записей списка как отдельных ресурсов и использование
PUT
иDELETE
(возможно, сETag
и/илиIf-Match
) кажется вариантом (PUT /lists/requiredItems/entries/3
,DELETE /lists/requiredItems/entries/1
PUT /lists/requiredItems/revision
), но как я могу убедиться, что все эти операции применяются, когда сеть падает посередине? цепочки обновлений? Разрешено ли HTTP PATCH работать с несколькими ресурсами? - Есть ли лучший способ «версировать» списки, возможно, неявно улучшая способ их обновления? Обратите внимание, что клиент определяет номер версии.
- Правильно ли запрашивать номер версии с помощью
GET /lists/requiredItems?property=revision
? Должен ли это быть отдельный ресурс, например/lists/requiredItems/revision
? Если это должен быть отдельный ресурс, как бы я обновил его атомарно (т. е. список и ревизия обновляются или оба не обновляются)? - Будет ли работать в патче JSON, чтобы сначала проверить значение ревизии на
3
, а затем обновить его до10
в том же патче?