我的问题是这样的:
我需要使用Datomic来建模:
请求架构如下:
:req/status ;; cardinality one. It can be: open, modified, approved, rejected
:req/things ;; cardinality many. [thing-id ...]
管理员从Web应用程序UI中查看用户请求。管理员有三种选择:批准,拒绝,修改。如果请求被批准或拒绝,则此请求不再存在。它将从管理员UI中消失。但是,如果请求被修改,它仍然可以被批准,被拒绝或再次被修改。修改请求时,只能修改req/things
。在该系统中,可能有多个管理员同时在同一请求上操作。
请求状态的状态图是:
open -> modified
modified -> modified
{modified, open} -> approved (done)
{modified, open} -> rejected (done)
考虑一种情况:两个管理员A和B处理相同的请求,他们互不感知。他们同时按下按钮。一个管理员A批准该请求,另一个管理员B修改该请求。该请求最初被修改过,因此当两个管理员处理它时,它处于modified
状态。
系统的正确行为可能有两种可能:管理员A的操作成功或管理员B的操作成功。如果管理员A的操作首先成功,则不再修改请求。如果管理员B的操作首先成功,则不应该批准A,因为req/things
已经被修改,但是管理员A批准了不同的req/things
集。
我考虑使用db.fn/cas
来保证只有一个admin A或admin B的操作可以成功。但是,db.fn/cas
在基数方面不起作用。
目前,我认为有两种方法可以解决我的问题(只有一个操作可以成功):
req/stamp
。标记最初为0.每个操作都会增加1.然后我可以使用此标记和db.fn/cas
来确保操作的逻辑严格性。我很好奇在Datomic中哪种方式更典型地解决了这个问题,还是有另一种方法可以解决这类问题?
一定不是专家,但我认为引入时间戳并在事务中对它进行比较对于这个用例来说更简单。