如何在datomic中撤消或撤消事务?

时间:2014-08-19 17:48:32

标签: clojure datomic

我意外地向datomic提交了一个事务,我想“撤消”整个事务。我确切知道它是什么交易,我可以看到它的数据,但我不知道如何从那里进行回滚交易。

2 个答案:

答案 0 :(得分:19)

基本程序:

  1. 检索要撤消的事务中创建的数据。使用事务日志查找它们。
  2. 删除与交易实体本身相关的数据:我们不想收回交易元数据。
  3. 反转所有剩余数据的“已添加”状态,即,如果添加了数据,撤消它,如果已撤消,则添加它。
  4. 反转反转数据的顺序,以便在重新声明旧旧值之前收回坏新值。
  5. 提交新交易。
  6. 在Clojure中,您的代码如下所示:

    (defn rollback
      "Reassert retracted datoms and retract asserted datoms in a transaction,
      effectively \"undoing\" the transaction.
    
      WARNING: *very* naive function!"
      [conn tx]
      (let [tx-log (-> conn d/log (d/tx-range tx nil) first) ; find the transaction
            txid   (-> tx-log :t d/t->tx) ; get the transaction entity id
            newdata (->> (:data tx-log)   ; get the datoms from the transaction
                         (remove #(= (:e %) txid)) ; remove transaction-metadata datoms
                         ; invert the datoms add/retract state.
                         (map #(do [(if (:added %) :db/retract :db/add) (:e %) (:a %) (:v %)]))
                         reverse)] ; reverse order of inverted datoms.
        @(d/transact conn newdata)))  ; commit new datoms.
    

答案 1 :(得分:0)

这并不是要回答原始问题,而是要让那些来自Google的人寻求有关如何回滚 datascript 交易的灵感。我找不到有关它的文档,所以我写了自己的文章:

(defn rollback
  "Takes a transaction result and reasserts retracted
  datoms and retracts asserted datoms, effectively
  \"undoing\" the transaction."
  [{:keys [tx-data]}]
  ; The passed transaction result looks something like
  ; this:
  ;
  ; {:db-before
  ;  {1 :post/body,
  ;   1 :post/created-at,
  ;   1 :post/foo,
  ;   1 :post/id,
  ;   1 :post/title},
  ;  :db-after {},
  ;  :tx-data
  ;  [#datascript/Datom [1 :post/body "sdffdsdsf" 536870914 false]
  ;   #datascript/Datom [1 :post/created-at 1576538572631 536870914 false]
  ;   #datascript/Datom [1 :post/foo "foo" 536870914 false]
  ;   #datascript/Datom [1 :post/id #uuid "a21ad816-c509-42fe-a1b7-32ad9d3931ef" 536870914 false]
  ;   #datascript/Datom [1 :post/title "123" 536870914 false]],
  ;  :tempids {:db/current-tx 536870914},
  ;  :tx-meta nil}))))
  ;
  ; We want to transform each datom into a new piece of
  ; a transaction. The last field in each datom indicates
  ; whether it was added (true) or retracted (false). To
  ; roll back the datom, this boolean needs to be inverted.
  (let [t
        (map
          (fn [[entity-id attribute value _ added?]]
            (if added?
              [:db/retract entity-id attribute value]
              [:db/add entity-id attribute value]))
          tx-data)]
    (transact t)))

通过首先捕获事务的返回值,然后将该返回值传递给回滚fn来使用它:

(let [tx (transact [...])]
  (rollback tx))

但是请注意,我是datascript / Datomic领域的新手,所以可能我缺少一些东西。

相关问题