Does ig/init-key
and ig/halt-key!
for a given key has to be defined in the same file?
I has always thought it doesn't matter, and the multimethods can be distributed all over the source files, but yesterday I come across this weird issue where I define ig/init-key in one file and ig/halt-key! in another, and the code in the ig/halt-key is not executed. It is executed though if they are in the same file.
I'm using integrant though duct, but I guess it doesn't really matter.
Is that correct behaviour? Any ideas what could be wrong?
Did you require both files?
You can add them in separate files, as long as both are requred
required where?
Anywhere in your program, if the file is never loaded then the multimethod won't be added to the global state
ha, works, thanks
👍
So clojure builds, kind of, a tree of lookups from the entry ns. Is that correct?
Right, from the entry ns your require tree starts. And whatever file gets required from that point is loaded before the -main
function.
And it since it works as a tree, all dependency :requires
are loaded too
Makes sense. I spent a few hours yesterday trying to figure out what is wrong. You probably saved me another few hours. Thanks!
If you're using the ig/load-namespaces
function then file name also matters https://github.com/weavejester/integrant/blob/32a46f5dca8a6b563a6dddf88bec887be3201b08/src/integrant/core.cljc#L195-L209
This could be the cause of your multiple file issue.
(Since the halt-key might not have been a compatible file name)
Yes, the key is not compatible with the file name. Actually I was wondering how James solved this. So he loads them based on key names. Makes sense. In my particular case, I was trying to implement shutdown process for datomic, but running only in dev mode, and only if I'm using dev-local. So I put another file datomic-dev.clj among dev sources.
(ns melon.infra.datomic-dev
(:require
[datomic.dev-local :as dl]
[duct.logger :refer [log]]
[integrant.core :as ig]))
(defmethod ig/halt-key! :melon.infra.datomic/conn-data
[_ {:keys [db-name config logger]}]
(when (= (:server-type config) :dev-local)
(let [db-config {:system (:system config)
:db-name db-name}]
(dl/release-db db-config)
(log logger :info :db-released db-config))))
So based on looking at load-namespaces
integrant won't be able to load this ns because the ns is not used as a prefix in config keys.
Based on your reply about require, I sorted out my issue by introducing middle ns called env-specific.clj (one in dev, one in prod sources) that just requires namespaces that could not be discovered the usual way.
(ns melon.system
(:require
...
[melon.env-specific]
...))
prod
(ns melon.env-specific)
dev
(ns melon.env-specific
(:require
[melon.infra.datomic-dev]))
What do you think about this workaround?Haven't heard of this use-case before (halt-key! is actually only meant for dev). Since you want this separate it sounds like you're using halt-key in production. If that's the case then I think this is a good solution (At least, I can't think of anything else right now)
I think halt-key! is used in production as well, for shutdowns. If you use Duct, you use it by default for shutdowns: • created system awaits daemons: https://github.com/duct-framework/core/blob/28de7df11af9c95ceb157d0c5163c061a75554b3/src/duct/core.clj#L242 • await-daemons adds shutdown hook to deinit system: https://github.com/duct-framework/core/blob/28de7df11af9c95ceb157d0c5163c061a75554b3/src/duct/core.clj#L227 So my ig/halt-key! would cause problems without source separation, I think.
Oh my bad, I think I was confused with suspend / resume keys.
I think your solution is good though
Once again thanks for help 🙇
You're welcome 😄