im trying to make a throw-away datomic system using juxt/clip
and try to clean up the created tmp db after stopping it.
i can't seem to figure out how can i pass a (clip/ref)
within the :stop
operation:
(defn default-schema-from-file []
(->> "datomic-schema.edn" io/resource slurp edn/read-string))
(defn tmp-in-mem-uri [] (str (gensym "datomic:<mem://tmp>-")))
(defn cleanup [uri conn]
(prn [uri conn])
(d/release conn)
(d/delete-database uri))
(defn tmp-parts []
{:datomic/schema
{:start `(default-schema-from-file)}
:datomic/uri
{:start `(tmp-in-mem-uri)}
:datomic/conn
{:pre-start `(d/create-database (clip/ref :datomic/uri))
:start `(d/connect (clip/ref :datomic/uri))
:post-start `(d/transact ~'this (clip/ref :datomic/schema))
:stop `(cleanup (clip/ref :datomic/uri) ~'this)}})
that (prn [uri conn])
debug statement prints:
[(clip/ref :datomic/uri) #object[datomic.peer.LocalConnection 0x63235b75 "datomic.peer.LocalConnection@63235b75"]]
so the ~'this
gets resolved as I expected but the (clip/ref :datomic/uri)
doesn'tI think there's a comment in the source about confirming refs in stop make sense.
yeah, i can see how it can pose unreconcilable constraints on the start/stop ordering... but in this case what shall i do? sounds like i would need to carry the dependencies of the stop process within the started component. but then will that component be still valid when im stopping the system?... 😕
or i could try to tease out this info from the connection object using something like this:
(.dbname ^datomic.peer.LocalConnection (sys :datomic/conn))
=> "tmp-17692"
i was trying to "inline" my small cleanup
function as:
:stop `(do (d/release (:conn ~'this))
(d/delete-database (:uri ~'this)))
then I got this error:
Execution error (ExceptionInfo) at juxt.clip.impl.core/evaluate-pseudo-clojure$fn (core.cljc:187).
Got null for function looking up symbol: do
this pseudo eval thing is quite fragile 😕
still no idea though how could be it done better...this feels like an ok compromise:
(defn cleanup-conn&db [{:keys [uri conn]}]
(d/release conn)
(d/delete-database uri))
(defn tmp-parts []
{:datomic/schema
{:start `(default-schema-from-file)}
:datomic/uri
{:start `(tmp-in-mem-uri)}
:datomic/conn
{:pre-start `(d/create-database (clip/ref :datomic/uri))
:start `{:uri (clip/ref :datomic/uri)
:conn (d/connect (clip/ref :datomic/uri))}
:resolve :conn
:post-start `(d/transact (:conn ~'this) (clip/ref :datomic/schema))
:stop `(cleanup-conn&db ~'this)}})
(comment
@(def sys-config {:components (tmp-parts)})
@(def sys (clip/start sys-config))
(clip/stop sys-config sys)
)
hmm... im also wondering how can i make this thing more modular, so i can create multiple datomic connections. the use-case would be to create a migration program, which transforms one datomic db into another one. but then i would need uri/schema/conn for each instance... so a started system would look something like this:
{:source-123/schema [,,,]
:source-123/uri "datomic:<dev://source-123>"
:source-123/data {:uri "datomic:<dev://source-123>"
:conn ^datomic.peer.Connection []}
:dest-234/schema [,,,]
:dest-234/uri "datomic:<dev://dest-234>"
:dest-234/data {:uri "datomic:<dev://dest-234>"
:conn ^datomic.peer.Connection []}}
Macros don't work, yeah :)
I didn't want a full clojure interpreter.
I wanted something that wasn't inventing a new syntax/form that wrapped function calls.
I think modularity and repetition is something I would address via transforms. This is essentially "tagging" your component with a key and having postwalk update it in some way.