Created
June 18, 2020 02:13
-
-
Save walterl/70607e342ea8bf6cd3f0b5b4c97379c8 to your computer and use it in GitHub Desktop.
Figuring out how to change all references to a duct component, with another component
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns overridetest.notworking | |
(:gen-class) | |
(:require [duct.core :as duct] | |
[integrant.core :as ig])) | |
(duct/load-hierarchy) | |
(derive ::daemon :duct/daemon) | |
(def config | |
{:duct.profile/base | |
{:duct.core/project-ns 'overridetest | |
::daemon {:email-client (ig/ref ::real-email-client) | |
:monitor (ig/ref ::monitor)} | |
::monitor {:email-client (ig/ref ::real-email-client)} | |
::real-email-client {}} | |
:duct.profile/dev | |
{;; I would _like_ to replace _all_ references to ::real-email-client with | |
;; references to ::dev-email-client, by _only_ adding to :duct.profile/dev. | |
;; In fact, ::real-email-client should not even be initialized. | |
;; Intuitively, the following is what I would expect to have to do to | |
;; override ::real-email-client with ::dev-email-client: | |
::real-email-client (ig/ref ::dev-email-client) | |
::dev-email-client {} | |
;; But it doesn't override references in ::monitor or ::daemon. It also | |
;; initializes both ::real-email-client _and_ ::dev-email-client. | |
;; The following works (and doesn't init ::real-email-client), but only | |
;; because I replace all references to ::real-email-client with | |
;; ::dev-email-client. | |
; ::daemon | |
; {:email-client (ig/ref ::dev-email-client)} | |
; ::monitor | |
; {:email-client (ig/ref ::dev-email-client)} | |
;; When there are many references to (e.g.) an email client in a system, it | |
;; becomes untenable to override each one individually. | |
} | |
:duct.profile/prod {}}) | |
(defmethod ig/init-key ::daemon | |
[_ config] | |
(println "INIT SERVER:" config) | |
:daemon) | |
(defmethod ig/init-key ::monitor | |
[_ config] | |
(println "INIT MONITOR:" config) | |
:monitor) | |
(defmethod ig/init-key ::email-client | |
[_ {:keys [impl]}] | |
(println "INIT EMAIL CLIENT:" impl) | |
[_ {:keys [impl]}]) | |
(defmethod ig/init-key ::real-email-client | |
[_ _] | |
(println "INIT REAL EMAIL CLIENT") | |
:real-email-client) | |
(defmethod ig/init-key ::dev-email-client | |
[_ _] | |
(println "INIT DEV EMAIL CLIENT") | |
:dev-email-client) | |
(defn -main [& args] | |
(let [keys (or (duct/parse-keys args) [:duct/daemon]) | |
profiles [:duct.profile/dev]] ; XXX Notice that this is not `:duct.profile/prod` | |
(-> config | |
(duct/exec-config profiles keys)))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns overridetest.working | |
(:gen-class) | |
(:require [duct.core :as duct] | |
[integrant.core :as ig])) | |
(duct/load-hierarchy) | |
(derive ::daemon :duct/daemon) | |
(def config | |
{:duct.profile/base | |
{:duct.core/project-ns 'overridetest | |
::daemon {:email-client (ig/ref ::email-client) | |
:monitor (ig/ref ::monitor)} | |
::monitor {:email-client (ig/ref ::email-client)} | |
;; In order to change all references in one place, I had to introduce an | |
;; intermediate component, with the sole purpose of referencing the | |
;; "implementation" component to use. | |
::email-client {:impl (ig/ref ::real-email-client)} | |
::real-email-client {} | |
} | |
:duct.profile/dev | |
{::dev-email-client {} | |
;; Then I need only change the implementation component, and all | |
::email-client {:impl (ig/ref ::dev-email-client)}} | |
:duct.profile/prod {}}) | |
(defmethod ig/init-key ::daemon | |
[_ config] | |
(println "INIT SERVER:" config) | |
:daemon) | |
(defmethod ig/init-key ::monitor | |
[_ config] | |
(println "INIT MONITOR:" config) | |
:monitor) | |
(defmethod ig/init-key ::email-client | |
[_ {:keys [impl]}] | |
(println "INIT EMAIL CLIENT:" impl) | |
;; It just returns the "implementation" component. | |
impl) | |
(defmethod ig/init-key ::real-email-client | |
[_ _] | |
(println "INIT REAL EMAIL CLIENT") | |
:real-email-client) | |
(defmethod ig/init-key ::dev-email-client | |
[_ _] | |
(println "INIT DEV EMAIL CLIENT") | |
:dev-email-client) | |
(defn -main [& args] | |
(let [keys (or (duct/parse-keys args) [:duct/daemon]) | |
profiles [:duct.profile/dev]] ; XXX Notice that this is not `:duct.profile/prod` | |
(-> config | |
(duct/exec-config profiles keys)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment