Моя проблема такова:
Мне нужно использовать Datomic для моделирования:
- Пользователь может предложить запрос. Изначально запрос находится в открытом состоянии.
- Администратор может утвердить / отклонить / изменить запрос пользователя.
Схема запроса имеет вид:
:req/status ;; cardinality one. It can be: open, modified, approved, rejected
:req/things ;; cardinality many. [thing-id ...]
Администратор видит запросы пользователя из пользовательского интерфейса веб-приложения. Есть три варианта для администратора: одобрить, отклонить, изменить. Если запрос одобрен или отклонен, то этот запрос больше не существует. Он исчезнет из интерфейса администратора. Однако, если запрос изменен, он все равно может быть утвержден, отклонен или изменен снова. Когда запрос изменяется, только req/things
может быть изменено. Может быть несколько администраторов, работающих одновременно по одному запросу в этой системе.
Диаграмма состояния статуса запроса:
open -> modified
modified -> modified
{modified, open} -> approved (done)
{modified, open} -> rejected (done)
Рассмотрим ситуацию:
Два администратора A и B обрабатывают один и тот же запрос, и они не чувствуют друг друга. Они нажимают кнопку одновременно. Один администратор A утверждает запрос, а другой администратор B изменяет запрос. Первоначально запрос был изменен, поэтому он обрабатывается двумя администраторами в состоянии modified
.
Правильное поведение системы может иметь две возможности: либо операция администратора A выполнена успешно, либо операция администратора B выполнена успешно. Если сначала операция администратора A прошла успешно, запрос больше не может быть изменен. Если сначала операция admin B прошла успешно, то одобрение A не должно произойти, потому что req/things
уже изменен, но администратор A утвердил другой набор req/things
.
Я думаю использовать db.fn/cas
, чтобы гарантировать, что только одна операция администратора A или администратора B может быть успешной. Однако db.fn/cas
не работает на кардинальности многих.
В настоящее время я думаю, что есть два способа решения моей проблемы (только одна операция может быть успешной):
добавить в схему дополнительную схему req/stamp
.
Изначально штамп равен 0. Каждая операция увеличивает его на 1. Затем я могу использовать этот штамп и db.fn/cas
, чтобы обеспечить логическую строгость операций.
Установите некоторую настраиваемую функцию db, такую как this , которая может сделать CAS на кардинальном множестве для обеспечения логической строгости.
Мне любопытно, какой путь в Datomic более каноничен для решения этой проблемы, или есть другой способ решения этой проблемы?