A very small library that adds
resume methods to Component.
In the reloaded workflow, each component is stopped completely before the codebase is refreshed. One problem with this approach is that it doesn't allow for connections held by components to persist during development.
Ideally we want a way of carrying open connections across a refresh of the codebase. This library introduces a new protocol,
Suspendable, that adds two new methods,
resume, for facilitating a "soft reset" of a system.
To install, add the following to your project
Essentially we want to replace uses of
suspend, in functions that are used to handle a reset.
(:require [clojure.tools.namespace.repl :refer [refresh]]
[suspendable.core :refer [Suspendable suspend resume]]
[your.app.system :refer [create-your-system]))
(defn suspend 
(alter-var-root #'system suspend))
(defn resume 
(alter-var-root #'system (partial resume (create-your-system))))
(defn reset 
(refresh :after 'user/resume))
If a component does not explicitly satisfy
Suspendable, it will be stopped and started as normal.
To write a component that can be suspended, you need to implement the
Suspendable protocol. For example, assume you already have a component that maintains some connection on a port. When we suspend the component, we want to keep the connection open, and when we resume the component, we want to reuse the same connection, but only if the port is the same.
(defrecord Foo [port]
(if (:connection component)
(assoc component :connection (open-connection port))))
(if-let [connection (:connection component)]
(do (close-connection connection)
(dissoc component :connection))
(resume [component old-component]
(if (= (:port component) (:port old-component))
(assoc component :connection (:connection old-component))
(do (component/stop old-component)
In the above case,
suspend does nothing special, but in other components it could be used to delay incoming data until the component is resumed.
resume method will only resume if the configuration for the connection (in this example, just the port) is the same. Otherwise we stop the old component and start the new component.
Copyright © 2016 James Reeves
Distributed under the MIT License.