Fork me on GitHub
#xtdb
<
2021-12-04
>
emccue03:12:28

Sorry to continue with the data model questions, but a pretty common operation we have is

(in-transaction
  (let [thing  (select-by-id 123)
        thing' (assoc thing :status "new-status")]
    (save! {:table "thing_status_changes"} {:from (thing/status thing)
                                            :to "new-status"})
    (save! thing')))
And in this context i don’t see a translation to xtdb. the magic “in-transaction” is what makes working with our “record” viable. For this particular thing i could say
learned that 123 has status "new-status"
In datomic, which doesn’t give bitemporality but would be still better than the current solution’s history maintaining bits how would we accomplish the same goal - recording that the status of a thing has transitioned from one status to another.

emccue04:12:31

match seems like it could be useful, but it doesn’t seem like i can know if it failed

cjmurphy05:12:18

I've been using transaction functions for mutations to existing documents. The idea being in the function you query the existing document then assoc onto it. Thus giving a change to an existing document. For knowing if the transaction has failed you can use this:

(let [tx-map (xt/submit-tx node tx)]
    (xt/await-tx node tx-map)
    (xt/tx-committed? node tx-map))

cjmurphy05:12:19

@U49U72C4V wrote a macro I've found very helpful for transaction functions: https://github.com/lgessler/glam/blob/master/src/main/glam/xtdb/easy.clj

🎉 2
emccue08:12:31

(require '[xtdb.api :as xt])

(def node (xt/start-node {}))

(xt/submit-tx node [[::xt/put {:xt/id 123
                               :status "started"}]])

(defn update-status [node thing-id to-status]
  (let [[[old-thing]] (seq (xt/q (xt/db node)
                                 '{:find  [(pull ?eid [*])]
                                   :where [[?eid :xt/id id]]
                                   :in    [id]}
                                 thing-id))
        new-thing      (assoc old-thing :status to-status)
        tx             (xt/submit-tx node [[::xt/match thing-id old-thing]
                                           [::xt/put new-thing]])
        most-recent-tx (xt/await-tx node tx)]
    (if (xt/tx-committed? node tx)
      {:new-thing new-thing
       :most-recent-tx most-recent-tx}
      (recur node thing-id to-status))))

(update-status node 123 "ended")

{:new-thing {:status "ended", :xt/id 123},
 :most-recent-tx #:xtdb.api{:tx-time #inst"2021-12-04T08:33:29.007-00:00", :tx-id 3}}

emccue08:12:40

I got a match based solution working

emccue08:12:24

im still really gonna need some convincing to think about transaction functions in a positive light

cjmurphy09:12:55

Interesting. I've got the feeling I'm over-using them. Will have to look at match . What's the negative about transaction functions?