CQRS с REST API - PullRequest
       112

CQRS с REST API

0 голосов
/ 09 июля 2020

Я создаю службу REST через CQRS с использованием EventSourcing для распределения изменений в моем домене по службам. У меня запущена и запущена служба REST с конечной точкой POST для создания начальной модели, а затем с серией конечных точек PATCH для изменения модели. Каждая конечная точка имеет связанную с ней команду, которую клиент отправляет как параметр Content-Type. Например, Content-Type=application/json;domain-command=create-project. У меня есть следующие конечные точки для создания записи проекта в моей службе управления задачами / проектами.

  • api.foo.com / project
    • Глагол: POST
    • Команда: create-project
    • Что он делает: Вставляет новую модель в хранилище событий с некоторыми установлены значения по умолчанию
  • api.foo.com / project / {projectId}
    • Verb: PATCH
    • Команда: rename-project
    • Что она делает: Вставляет событие project-renamed в хранилище событий с новым именем проекта.
  • api.foo.com / project / {projectId}
    • Глагол: PATCH
    • Команда : reschedule-project
    • Что он делает: Вставляет событие project-rescheduled в хранилище событий с новым сроком выполнения проекта.
  • api.foo.com / project / {projectId}
    • Глагол: PATCH
    • * 10 70 * Команда: set-project-status
    • Что она делает: Вставляет событие project-status-changed в хранилище событий с новым статусом проекта (Активный, Планирование, Архивные и т. Д. c).
  • api.foo.com / project / {projectId}
    • Глагол: УДАЛИТЬ
    • Команда: delete-project
    • Что она делает: Вставляет событие project-deleted в хранилище событий

Традиционно в службе REST вы предлагаете конечную точку PUT, чтобы можно было заменить запись. Я не уверен, как это работает в шаблоне событий + CQRS. Могу ли я когда-либо использовать только глаголы POST и PATCH?

Я был обеспокоен тем, что я слишком детализирован и что для каждого поля не нужна связанная с ним команда. Конечная точка PUT может использоваться для замены частей. Меня беспокоило, что хранилище событий не синхронизируется c, поэтому я просто придерживался конечных точек PATCH. Типичен ли такой уровень детализации? Для модели с 6 свойствами на ней У меня есть 5 команд для настройки свойств модели.

Ответы [ 3 ]

2 голосов
/ 09 июля 2020

Один вопрос, который приходит в голову: является ли REST правильной парадигмой для CQRS?

Один совершенно другой способ структурировать это - не иметь конечных точек, ориентированных на действия, а вместо этого структурировать REST API как серия событий, к которым вы добавляете новые события (с помощью POST).

События должны быть неизменяемыми и доступными только для добавления, поэтому, возможно, метод DELETE не имеет большого смысла для мутаций.

Если вы идете ва-банк с CQRS (удачи, я слышал истории о войне), я был бы склонен создать API, который хорошо отражает эту модель.

1 голос
/ 10 июля 2020

Это распространенный вопрос, который мы получаем много времени, когда помогаем разработчикам начать работу с CQRS / ES. Мы должны признать, что применение REST в чистом виде - действительно плохое совпадение с DDD / CQRS, поскольку назначение команд явно не выражено в глаголах GET / POST / PUT / PATCH / DELETE (даже если вы можете используйте content-type как и вы). Также C / R-сторона системы - это определенно разные ресурсы в CQRS-системе, которая не соответствует REST.

Однако использование HTTP для предоставления API для системы CQRS / ES очень практично.

Обычно мы используем только POST для отправки команд либо на конечную точку /commands, либо на конечные точки с именем команды, то есть /commands/create-project. Все дело в том, насколько строгим вы хотите быть. В этом случае мы встраиваем тип команды в полезную нагрузку или как тип содержимого.

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

Удачи!

1 голос
/ 10 июля 2020

Могу ли я использовать только глаголы POST и PATCH?

В большинстве случаев вы будете использовать POST.

PUT, а PATCH определены с удаленным созданием семантика - это методы, используемые для копирования новых представлений ресурса с клиента на сервер. Например, клиентское GET sa представление /project/12345, вносит локальные изменения, а затем использует PUT, чтобы запросить, чтобы сервер принял новое представление ресурса клиента как свое собственное.

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

Теперь технически документация PATCH накладывает какие-либо ограничения на то, что такое «патч-документ». Однако для того, чтобы PATCH был более полезным, чем POST, нам нужны форматы документов исправлений, которые являются универсальными и широко признанными (например, application/merge-patch+json или application/json-patch+json).

И это не совсем случай, который у вас есть здесь, где вы определяете командные сообщения, которые c относятся к вашему домену.

Более того, семантика удаленного создания не очень хорошо согласуется с «моделированием домена» (которое является частью наследия CQRS). Когда мы моделируем домен, мы обычно даем модели домена право решать, как интегрировать новую информацию с тем, что сервер уже знает. Семантика PUT и PATCH больше похожа на то, что вы использовали бы для записи информации в хранилище данных anemi c.

С другой стороны, можно использовать POST

POST служит многим полезным целям в HTTP, включая общую цель «это действие не стоит стандартизировать». - Fielding, 2009

Можно вспомнить, что REST - это архитектурный стиль всемирной паутины, и единственный небезопасный метод, поддерживаемый html, - это POST.

Поэтому замените команды PATCH на POST, и вы на правильном пути.

Fielding, 2008

Я также должен отметить, что приведенное выше не но полностью RESTful, по крайней мере, как я использую этот термин. Все, что я сделал, это описал сервисные интерфейсы, что не больше, чем у любого RP C. Чтобы сделать его RESTful, мне нужно было бы добавить гипертекст, чтобы представить и определить службу, описать, как выполнять сопоставление с использованием форм и / или шаблонов ссылок, и предоставить код для объединения визуализаций полезными способами. Я мог бы даже go дальше и определить эти отношения как стандартные, так же, как Atom стандартизировал нормальный набор HTTP-отношений с ожидаемой семантикой.

То же самое и здесь - мы еще не достигли " REST ", но мы улучшили ситуацию, выбрав стандартизированные методы, которые лучше соответствуют нашей предполагаемой семантике.

И последнее замечание - вам, вероятно, также следует заменить использование DELETE на POST. DELETE потенциально является проблемой по двум причинам: семантика не такая, как вы хотите, и стандартная полезная нагрузка удаления имеет не определена семантика

Выражается по-другому: DELETE из передача документов по сети домен, а не ваш домен. Следует понимать, что сообщение DELETE, отправленное вашим ресурсам, означает то же самое, что и сообщение DELETE, отправленное на любой другой ресурс. Это единое ограничение интерфейса в действии: мы все согласны с тем, что токены HTTP-методов означают одно и то же везде .

Относительно небольшое количество ресурсов позволяет использовать метод DELETE - его основное использование для сред удаленного авторинга, где у пользователя есть какое-то направление в отношении его воздействия - RF C 7231

Как и раньше: семантика удаленного авторинга явно не подходит для отправки сообщения модели предметной области.

...