如何在Datomic中需要广义比较和交换语义的情况下进行设计?

问题描述 投票:3回答:1

我的问题是这样的:

我需要使用Datomic来建模:

  1. 用户可以提出请求。最初,请求处于打开状态。
  2. 管理员可以批准/拒绝/修改用户请求。

请求架构如下:

: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中添加一个额外的架构req/stamp。标记最初为0.每个操作都会增加1.然后我可以使用此标记和db.fn/cas来确保操作的逻辑严格性。
  • 安装一些自定义的数据库函数,如this,它可以在基数上做CAS,以确保逻辑严格。

我很好奇在Datomic中哪种方式更典型地解决了这个问题,还是有另一种方法可以解决这类问题?

clojure datomic compare-and-swap
1个回答
0
投票

一定不是专家,但我认为引入时间戳并在事务中对它进行比较对于这个用例来说更简单。

© www.soinside.com 2019 - 2024. All rights reserved.