Before applying a fairly extensive data transaction, I’d like to assure myself that I can easily restore the database to a specific point in time. Obviously I have datomic’s external restore capability to rely on, which is great, but for the purpose of this exercise, I’d like to generate a txn that, when applied, ensures that the contents of the user partition match the contents of the user partition at a given time.
I sketched this out, does anyone see any obvious flaws:
(defn restore-to
[db t]
(let [db' (d/as-of db t)
user-vs-by-ea (reduce (fn [accum [e a v]]
(cond-> accum
;; only look at entities in the user partition
(= 4 (d/part e))
(update [e a] (fnil conj #{}) v)))
{}
(seq (d/datoms db :eavt)))]
(into []
(mapcat (fn [[[e a] vs]]
;; vs are whare are currently true
;; vs' are what we want to be true
(let [vs' (set (map :v (seq (d/datoms db' :eavt e a))))]
(concat
(for [v (set/difference vs' vs)]
[:db/add e a v])
(for [v (set/difference vs vs')]
[:db/remove e a v])))))
user-vs-by-ea)))
Obviously here the entire datom set has to fit in memory, though one could do it in a single lazy pass by keeping track of the current e and a values. Performance aside, are there any problems I have not foreseen?