-
Notifications
You must be signed in to change notification settings - Fork 64
Description
Hi @weavejester,
As discussed on Slack, we talked about how integrant's halt-key! method could have access to the original init-key arguments. It was the following example that spurred the discussion:
(defmethod ig/init-key ::datasource
[_ {:keys [logger]}]
(log logger :info ::starting.datasource)
(hikari/make-datasource ...))
(defmethod ig/halt-key! ::datasource
[_ datasource]
(log ??? :info ::closing.datasource)
(.close datasource))How to access the logger at the ??? in halt-key? A solution would be to have the following:
(defmethod ig/init-key ::datasource
[_ {:keys [logger]}]
(log logger :info ::starting.datasource)
{:datasource (hikari/make-datasource ...)
:logger logger})
(defmethod ig/halt-key! ::datasource
[_ {:keys [datasource logger]}]
(log logger :info ::closing.datasource)
(.close datasource))However, in my opinion this exposes an implementation detail (::datasource wanting to access the logger, so the actual datasource is inside a map) to the "consumers" of this component.
We discussed three possible solutions.
- Adapting
halt-key's arguments to something like[_ pre-init-value post-init-value]. Upside is, that this is fairly straightforward. Downside is, it's not clear how to do this without breaking backward compatibility. The example however would be changed to the following:
(defmethod ig/halt-key! ::datasource
[_ {:keys [logger]} datasource]
(log logger :info ::closing.datasource)
(.close datasource))- Adding an
Unrefprotocol having anunreffunction, together with some helper functions. Integrant will callunrefifinit-key's return value satisfies theUnrefprotocol, before passing it to other components. For example:
(defrecord Datasource [datasource logger]
Unref
(unref [_] datasource))
(defmethod ig/init-key ::datasource
[_ {:keys [logger]}]
(log logger :info ::starting.datasource)
(map->Datasource
{:datasource (hikari/make-datasource ...)
:logger logger}))Or, with some helper function:
(defmethod ig/init-key ::datasource
[_ {:keys [logger]}]
(log logger :info ::starting.datasource)
(ig/expose :datasource
{:datasource (hikari/make-datasource ...)
:logger logger}))Benefits of this approach are backward compatibility and the developer can keep even more values than just the pre-init value.
- A workaround for now without changing integrant, by using the
::buildmetadata on a system.
As I also stated on Slack, I am just getting started with Integrant, so we agreed we would both ponder if this is an actual problem, and if so, what the best approach would be to solve it.