integrant

michaelwhitford 2025-03-12T17:28:52.407969Z

I am having a bit of a chicken-or-the-egg problem. I created a tiny implementation to illustrate the issue. Details in thread.

michaelwhitford 2025-03-12T17:30:13.018559Z

(ns bbmcp
  (:require [clojure.pprint :refer [pprint]]
            [integrant.core :as ig]))

(defn in2out
  ([]
   (in2out *in* *out*))
  ([reader writer]
   (loop []
     (let [line (.readLine reader)]
       (.write writer (str line "\n"))
       (flush))
     (recur))))

(def config
  {:adapter/in2out {:blah 1}})

(defmethod ig/init-key :adapter/in2out [_ {:keys [blah] :as opts}]
  (in2out))

(defmethod ig/halt-key! :adapter/in2out [_]
  (println "Shutting down...")
  (System/exit 0))

(defn -main [& args]
  (println "Args:")
  (pprint args)
  (.addShutdownHook (Runtime/getRuntime) (Thread. (fn [] (ig/halt! system))))
  (def system (ig/init config)))

(comment
  (apply -main [1 2 3])
  (pprint [1 2 3]))
If I move the system definition up 1 line it works, but the shutdown hook is never defined because the init runs a loop.

michaelwhitford 2025-03-12T17:31:05.693169Z

I tried using {} and nil for system in the halt! but it gives exceptions because it is not an integrant init object.

michaelwhitford 2025-03-12T17:32:07.022949Z

The real app I am creating will need to do cleanup from the shutdown hook, this is just a toy implementation to play with and show the issue.

weavejester 2025-03-12T17:42:11.245169Z

The in2out function should run its loop in a separate thread. Integrant expects the init-key method to return before moving onto the next key, so having an infinite loop during initiation will prevent any keys that depend on :adapter/in2out from being run.