Fork me on GitHub
#xtdb
<
2024-02-07
>
zeitstein12:02:14

Invoking the following test through the terminal, the process does not exit:

(ns test
  (:require
   [xtdb.api :as xt]
   [clojure.test :refer :all]))

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

(deftest foo (is (= 1 1)))
This is with XT 1.24.3. Is this expected behaviour? I imagine one needs to .close the node, but naively appending (.close node) to that file throws java.lang.IllegalStateException: TxLog is closed. which I guess makes sense. For more context, I'd like to submit the tx a single time, then run many tests over that node. Using fixtures would help with that, but the issue remains if I require a ns that has an XT node started in it. Is there a simple way out? 🙂

zeitstein12:02:40

The not simple way out: lift starting the node from the ns containing XT logic, so I could require it in tests.

zeitstein12:02:55

Edited the example to be even more simple 🙂

jarohen12:02:00

yep, you've got it, the node will need to be closed. we usually either go for test fixtures, as you say, or if all the references to the node are within a certain scope, a with-open

jarohen12:02:22

in your case, sounds like a :once fixture to start up and tear down the node should do the trick?

(def ^:dynamic *node* nil)

(t/use-fixtures :once
  (fn [f]
    (with-open [node (xt/start-node {})]
      (xt/submit-tx node ...)
      (binding [*node* node]
        (f)))))
?

zeitstein12:02:15

Not if I have a foo.xt-logic that does (def node (xt/start-node {})) and then I require it in the test ns.

jarohen12:02:39

can the functions in foo.xt-logic take the node as a parameter?

zeitstein12:02:02

They already do, yep. Just need to lift the node itself somewhere else.

👍 1
zeitstein12:02:41

It would be nice to have a workaround, though. E.g. to support using hyperfiddle/rcf tests throughout the ns. (https://clojurians.slack.com/archives/C7Q9GSHFV/p1706818329319899, same issue.) It works fine at the REPL, so maybe that's enough.

zeitstein12:02:19

It's obviously my poor hygiene at fault, just wondering if there's a workaround.

jarohen12:02:44

fair, yep - something like integrant/integrant.repl, perhaps, to manage the lifecycle? :thinking_face:

zeitstein12:02:37

Only have a server and XTDB, so I'm resisting adding more perhaps unnecessary complexity 🙂

jarohen12:02:48

also fair 🙂

🙂 1
zeitstein12:02:50

Thanks for your time gratitude

jarohen12:02:10

yw 🙂 🙏

zeitstein13:02:36

This might be convenient at the REPL (as long as you run the tests manually or through rcf) and it exits properly:

(ns test
  (:require
   [xtdb.api :as xt]
   [clojure.test :refer :all]
   [hyperfiddle.rcf :refer [tests]]))

(def node (xt/start-node {}))
(xt/submit-tx node [[::xt/put {:xt/id 1}]])
(xt/sync node)

(use-fixtures :once
  (fn [t]
    (t)
    (.close node)))

(deftest bar
  (is (= (xt/entity (xt/db node) 1)
         {:xt/id 1})))

(tests
  (xt/entity (xt/db node) 1) := {:xt/id 1})

seancorfield18:02:18

I'm going to reinforce the "poor hygiene" aspect and note that top-level content in namespaces (`def` and other non-`defn` expressions) should never have any side-effects -- those things happen when you load a namespace, so they'll happen if any tooling loads your namespace to analyze it or if you try to compile the namespace. It really is a good practice to adopt to always put side-effects into functions so you can control when they happen.

1
🙏 1
zeitstein08:02:14

Thanks for jumping in, Sean! Spurred on by your comment (James was too gentle 😁), I took the time to clean this up. I also accepted that not all tests can/should be 'inlined'. (This was in turn inspired by some of Sean's arguments I found online.)

jarohen10:02:50

> James was too gentle 😁 noted for next time 😈

😁 2