xtdb

Vladimir Pouzanov 2024-11-28T20:08:35.367399Z

I'm slightly confused about transactions in xtdb v2. With v1 I can use xt/entity-history to figure out the transactional (not temporal) history of a given document. Moreover, with xt/open-tx-log I can then go from a transaction id to what else happened within the context of the same transaction. In v2 I can query '(from :xt/txs [*]) which gives me the transactions without the context of what happened in them, and I can't find any meaningful way to go from a document version to the transaction that created it. Am I missing something or that API isn't available (yet)?

Vladimir Pouzanov 2024-11-28T20:25:08.827999Z

ah, I see. So the _system_from is effectively the long-form transaction id and it's unique. Is there anything like xt/open-tx-log to see what else happened during that transaction?

refset 2024-11-28T20:35:09.164329Z

Yes _system_from should always be unique, and we even now disallow transactions happening in the same microsecond (...but that's not relevant for quite some time unless hardware improves dramatically πŸ™‚) Discovering changes across all tables isn't easy right now - you have to enumerate all the tables (e.g. by querying information_schema.tables) and do a UNION ALL while joining on the _system_from. I would really like to make this simpler but we haven't discussed potential designs in much depth yet. If you need those lookups to be fast though then you may want to consider maintaining your own metadata of tables have been changed by the current transaction (stored in some user-defined table or column, similar to https://discuss.xtdb.com/t/corrections-table-pattern-for-tracking-changes/467). What's the requirement you're hoping to solve?

Vladimir Pouzanov 2024-11-28T20:43:25.525529Z

I'm just tinkering for now. The conceptual problem I'm solving is "what were the transaction submitted between A and B and which records they affected?" I have somewhat a "blockchain" proof of concept (a bastardized storage solution that removes all the insanity of a distributed consensus and basically turns it into a transaction log and a computed state). I don't like it and I really want to get rid of all that and looking for options. Insofar v1's xt/open-tx-log does almost what I want (sans tracking the failed transactions which is something I can work around with functions, I think). datomic's log api also seems to do something very similarβ€”I'm not fully sold yet on if I need actual bitemporality for my case as I just need to know "where we are now" and "how we got here".

πŸ‘ 1
refset 2024-11-28T21:03:31.484509Z

Thanks for the added context - always useful! Is it a very routine / 'hot path' query to be running in your application? Does it need to be fast? Or just possible?

Vladimir Pouzanov 2024-11-28T21:03:58.988419Z

"just possible" at the moment

πŸ‘ 1
Vladimir Pouzanov 2024-11-28T21:04:41.697969Z

and yeah, I know that it's a broad answer. I could do "just possible" with sqlite and lots of code πŸ™‚ I'd prefer the db layer to do it for me, though

πŸ’― 1
refset 2024-11-28T21:05:22.109869Z

Bitemporality is particularly useful when the "transactions submitted" and "records affected" are happening in upstream systems, rather than the one that XTDB is underpinning

Vladimir Pouzanov 2024-11-28T21:08:12.734509Z

ah, that actually makes more sense when you put it like that!

πŸ™‚ 1
refset 2024-11-28T21:37:37.152679Z

Incidentally there was a https://discuss.xtdb.com/t/relate-given-transaction-to-affected-documents/410/4 thread roughly about this already (by @stefcoetzee, no less), so I just updated that with this example too πŸ™‚

🫑 1
Stef Coetzee 2024-11-29T01:56:33.640129Z

A document history in XTQL focused on one table (`store`):

(defn doc-history
  "History of document with `:xt/id` of `xt-id` from `store`,
  in descending order from most recent to oldest version."
  [store xt-id]
  (mapv #(into (sorted-map) %)
        (pt/q (xt/template
               (-> (from ~store
                         {:bind [{:xt/id ~xt-id}
                                 * xt/valid-from xt/system-from]
                          :for-valid-time :all-time})
                   (order-by {:val xt/valid-from
                              :dir :desc}))))))

Stef Coetzee 2024-11-29T03:34:46.295109Z

Should add, where pt/q is defined as:

(defn q [query & opts]
  (with-open [node (xtc/start-client http-node-url)]
    (xt/q node query opts)))
where xtc is xtdb.client