我想在没有触发副作用的情况下操作Datomic数据库。我们的目标是开发一种替代方案"当前数据库的版本,如果替代版本的创建成功,则提交数据。否则,数据库连接应保持其当前状态。
我发现datomic.api / with非常适合我的问题,但我不知道将替代版本中创建的数据添加到Datomic连接的最佳方法是什么。
这是我目前的程序:
(defn operation [conn]
(let [db (d/db conn)
current-t (d/basic-t db)
new-db (create-alternative-version db)]
(d/transact conn (d/datoms (d/since new-db current-t) :eavt))))
目前,我收到以下错误:
ClassCastException datomic.db$datoms$reify__1559
cannot be cast to java.util.List datomic.api/transact
您认为这种方法有意义吗?如果有更好的解决方案?
我也查看了sync api,但它似乎不适合这个目的。
感谢您的帮助
答案 0 :(得分:1)
交易者的with-db和db之间没有同步生效。 with-db是另一种现实,并不会对交易者连接或交易者的当前数据库持有任何锁定。
举一个例子,考虑你每d /做一个事务,然后得到一个with-db,一个应用了事务的推测数据库状态。然后检查生成的数据库状态是否成功" (你还没有澄清成功的意义,但我认为它需要检查整个结果db状态的部分)。无法保证同一事务会导致真实数据库的状态相同,因为其他事务可能发生在两者之间。
此同步问题的典型解决方案是确定"成功"的最小检查。并在事务功能中实现它。在事务函数中,您可以在事务之前访问一致的数据库状态。事务处理函数在事务期间独立运行,如果不能导致事务成功,则可用于使事务失败。数据库状态。让事务失败的替代方法是在事务之前从数据库状态注入数据。如有必要,您可以在交易功能中使用d/with
。
以下是交易功能的文档:http://docs.datomic.com/database-functions.html
您的示例不起作用,因为d / datoms返回eavt元组,而事务需要以:db/add
,:db/retract
或事务函数的标识开头的断言元组,或者用于upsertion的映射。你当然可以将eavt元组转换为这样的断言元组,但是你会错过撤销(可以使用d / history,IDK)。将您应用于d/with
的同一交易应用于d/transact
会更容易。然而,如上所述,这不会给你任何同步保证。