-
Notifications
You must be signed in to change notification settings - Fork 18
Description
I encountered a problem when using an external config, which is only relevant for repl-driven development. For example, let's take part of the system.
(def dev-system
{::ds/defs
{:service
{:api-server
#::ds{:start
(fn [{deps ::ds/config
system ::ds/system}]
(let [global-config (get-in system [::ds/defs :components :global-config])
{:keys [service-map]} global-config
{:keys [main-db]} deps]
(-> service-map
(create-api-server)
(http/start))))
:stop (fn [{api-server ::ds/instance}]
(when api-server
(http/stop api-server)))
:config {:main-db (ds/ref [:components :postgres-db])}}}
:components
{:global-config (load-file "config/development.clj")}
...}})
;; prepare repl instance
(defmethod ds/named-system ::ds/repl
[_]
(ds/system dev-system))Then call (donut.system.repl/restart)
- The first launch will go fine and we will receive an instance of our system.
- Now let’s change something in the config that we pull from an external file, for example the port number for the server
- Restart and port number is still old. unexpected behaviour
This happens because the state of our system, described in dev-system def, was baked in at the moment when the namespace was loaded. Changes have occurred, but in a third-party file config/development.clj and there were no changes in the namespace containing the system and it did not need to re-evaluate ns.
I also doublecheck example from organization and configuration section of donut.system readme. Config also not reload in proposed solution. It's possible that I'm doing something wrong.
(defmethod ds/named-system :dev
[_]
(ds/system :base {[:env] (env-config :dev)}))
(defmethod ds/named-system :donut.system/repl
[_]
(ds/system :dev))We have several options to get around this
- We can make
dev-systemdefn instead of def
(defn dev-system
[]
{::ds/defs
{:service
{:api-server
...}}})
;; now call as fn when prepare repl instance
(defmethod ds/named-system ::ds/repl
[_]
(ds/system (dev-system)))- We can wrap our user ns like this
(defn restart
[]
(require 'my-project.system :reload)
(donut.system.repl/restart))I don’t think the problem is relevant for running in production or test mode. But for repl development, this behavior was unexpected for me and I did not immediately understand why this was happening.
Ideally if donut.system.repl/restart respect this case. Or it can clearly indicate in the documentation that by loading a config from an external source via Aero or a similar method to system defined with def, there is a chance to shoot in the legs.