Fork me on GitHub
#integrant
<
2021-06-24
>
greg08:06:34

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?

Kevin08:06:11

Did you require both files?

Kevin08:06:29

You can add them in separate files, as long as both are requred

greg08:06:04

required where?

Kevin08:06:39

Anywhere in your program, if the file is never loaded then the multimethod won't be added to the global state

greg08:06:47

ha, works, thanks

greg08:06:36

So clojure builds, kind of, a tree of lookups from the entry ns. Is that correct?

Kevin08:06:37

Right, from the entry ns your require tree starts. And whatever file gets required from that point is loaded before the -main function.

Kevin08:06:12

And it since it works as a tree, all dependency :requires are loaded too

greg08:06:09

Makes sense. I spent a few hours yesterday trying to figure out what is wrong. You probably saved me another few hours. Thanks!

Kevin08:06:28

This could be the cause of your multiple file issue.

Kevin08:06:38

(Since the halt-key might not have been a compatible file name)

greg09:06:28

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?

Kevin09:06:40

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)

greg09:06:22

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.

Kevin09:06:37

Oh my bad, I think I was confused with suspend / resume keys.

Kevin09:06:09

I think your solution is good though

greg09:06:46

Once again thanks for help šŸ™‡

Kevin09:06:59

You're welcome šŸ˜„