Как реализовать сложные условные массовые частичные обновления через JSON API?

2

Существуют методы POST и PATCH в HTTP-протоколе для частичных обновлений. В методе PATCH для JSON API есть RFC 5789, RFC 6902, RFC 7396.

Но у меня есть вопрос, связанный с большими ресурсами, которые необходимо частично обновить с довольно сложными условиями.

Скажем, у нас есть API endpont "/members" который похож на большую коллекцию с тысячами записей, где каждая запись содержит десятки полей. Поэтому клиенты частично читают эти значения с помощью метода "GET/members?fields=f1,f2,f3" с разбиением на страницы, и каждый клиент читает только подмножество полей, необходимых для их текущей задачи.

Чтобы упростить вопрос, предположим, что у любой записи есть одно обязательное поле "email" для идентификации и несколько необязательных полей.

{
"email": "[email protected]",
"optional1": "x",
"optional2": "x",
"optional3": "x"
}

И у нас есть два клиента, работающих параллельно, чтобы создавать и обновлять новые записи навалом. Но каждый клиент хочет переписать только их подмножество необязательных полей.

Таким образом, клиент A отправит запрос с значениями A для массового патча, которому будет разрешено перезаписать значение поля "optional1" только потому, что это поле имеет важное значение для их задачи. И этот клиент также укажет значение для поля "optional2" для новых записей. И этот клиент вообще не указывал поле "optional3".

{
"email": "[email protected]",
"optional1": "A",
"optional2": "A"
}

Хотя эта запись новая, она полностью записывается в хранилище. Затем клиент B отправляет запрос с значениями B для массового патча, который может быть заменен значением поля "optional2" только потому, что это поле имеет важное значение для их задачи.

{
"email": "[email protected]",
"optional1": "B",
"optional2": "B",
"optional3": "B"
}

Поскольку запись уже существует, поле "optional1" этой записи должно оставаться с тем же старым значением A поскольку это поле не имеет существенного значения, значение поля "optional2" должно быть перезаписано новым значением B потому что это поле имеет важное значение и значение поля "optional3" должно получить значение B потому что это поле было просто пустым. Объединенный результат действий должен быть следующим.

{
"email": "[email protected]",
"optional1": "A",
"optional2": "B",
"optional3": "B"
}

Таким образом, поведение зависит от наличия записи. Как вы, ребята, реализуете это в JSON API многоразового метода конечных точек для параллельных параллельных частичных обновлений таких коллекций со сложными условиями, которые позволят клиентам этого API перезаписывать только подмножество полей в записи, если эта запись уже существует и содержит некоторые значения?

Решение RFC 6902 не соответствует, потому что их операции add и replace фактически заменяют значение.

add - Если целевое местоположение указывает член объекта, который существует, это значение члена заменяется.

replace - Операция "replace" заменяет значение в целевом местоположении новым значением. Объект операции ДОЛЖЕН содержать элемент "значение", содержимое которого указывает значение замены.

Вы можете видеть, как это соответствует методу Java Map.put().

Если в карте ранее содержалось сопоставление для ключа, старое значение заменяется указанным значением.

Но недостающая функция соответствует скорее методу Java Set.add().

Добавляет указанный элемент к этому набору, если он еще не присутствует (дополнительная операция). Более формально добавляет указанный элемент e к этому набору, если в наборе нет элемента e2, такого, что (e == null? E2 == null: e.equals(e2)). Если этот набор уже содержит элемент, вызов оставляет его неизменным и возвращает false.

Как бы вы создали JSON API, который позволил бы использовать оба типа операций для массового патча очень большой коллекции с элементами, содержащими в себе десятки необязательных полей?


Обновить

Благодаря @chad-jensen за идею правил приоритетности атрибутов. Указанный документ предлагает довольно гибкий подход, поэтому я попытался адаптировать его к моим потребностям. Я думаю, что у меня будет две операции: "инициализировать" с более низким приоритетом и "добавить" или, скорее, "заменить" более высоким приоритетом.

Затем в моем примере данные JSON, отправленные клиентом A и клиентом B, будут следующими.

Данные, отправленные клиентом A, который обновляет поле "optional2" с более низким приоритетом и обновляет поле "optional1" с наивысшим приоритетом.

{
    "email": "[email protected]",
    "initialize":
    {
        "optional2": "A"
    },
    "replace":
    {
        "optional1": "A"
    }
}

Данные, отправленные клиентом B, который обновляет поля "optional1" и "optional3" с более низким приоритетом и обновляет поле "optional2" с наивысшим приоритетом.

{
    "email": "[email protected]",
    "initialize":
    {
        "optional1": "B",
        "optional3": "B"
    },
    "replace":
    {
        "optional2": "B"
    }
}
  • 0
    Вы уверены, что этой архитектуре не нужен какой-то промежуточный уровень (мне хочется сказать, база данных) для управления всеми этими одновременными обновлениями, проверками полномочий и т. Д.? Я не вижу, как вы собираетесь проверять эти обновления, например, для управления инцидентами, для начала. Я без сомнения пропускаю что-то главное, хотя!
  • 0
    Конечно, будет и аудит, и база данных, и все остальное. Вопрос скорее касался формата данных JSON для передачи, который позволял бы устанавливать разные приоритеты источника для каждого поля. Кстати, я обновил исходный вопрос решением, которое пришло из этой идеи уровней приоритетов атрибутов.
Теги:
rest
http-patch

1 ответ

0

Вам потребуется какое-то сопоставление приоритетов, которое определяет, какие поля приоритеты для каждого клиента.

Кажется, что у вас уже есть это, но я собираюсь предположить, что он где-то хранится/сервер и клиент знают о том, в каком поле они имеют наивысший приоритет (приоритет). Вам также может потребоваться узнать, какой клиент обновил последнее поле.

С учетом сказанного вы должны иметь возможность сделать aa null/empty/check для каждого атрибута и только заменить значения, когда они являются значением по умолчанию (null/empty string). В сценарии, когда значение уже заполнено, вам нужно будет проверить, имеет ли входящий клиент более высокий/меньший приоритет, чем тот, кто последний раз обновлял значение.

Я нашел документ, который может прояснить, что я имею в виду (он немного разбирается в некоторых сторонних инструментах, но существует концепция): https://www.ibm.com/support/knowledgecenter/en/SSPLFC_7.2.0/UserGuide/c_cmdb_reconcilation_overview.html

  • 1
    Спасибо, Чед. Я изучил упомянутый документ и создал решение, основанное на уровнях приоритетов атрибутов. Вы можете увидеть это в моем обновленном тексте вопроса.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню