Last active
January 15, 2021 20:25
-
-
Save aroemers/faf64663a5673a664afc971fe8ebf150 to your computer and use it in GitHub Desktop.
Component-lite
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 app | |
(:require [lifecycle :refer [combine parallel]])) | |
(defn components [app-config] | |
(combine (parallel (users-db/component) | |
(tasks-db/component)) | |
(rest-api/component app-config))) |
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 core | |
(:require [lifecycle :refer [start stop combine]])) | |
(defn -main [& args] | |
(let [component (combine (logger/component) | |
(jdbc/component jdbc-config) | |
(app/components app-config)) | |
system (start component {})] | |
;; bonus: the empty map above could be filled by another | |
;; lifecycle library/approach. | |
... | |
(stop component system))) |
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 jdbc | |
(:require [hikari-cp.core :as hikari] | |
[lifecycle :refer [Lifecycle]])) | |
(defn component [config] | |
(reify Lifecycle | |
(start [_ {:keys [logger]}] | |
(logger "starting JDBC pool...") | |
{:jdbc (hikari/make-datasource config)}) | |
(stop [_ {:keys [logger jdbc]}] | |
(logger "stopping JDBC pool...") | |
(hikari/close-datasource jdbc)))) |
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 lifecycle) | |
(defprotocol Lifecycle | |
:extend-via-metadata true | |
(start [this system] | |
"Starts the component, using the given system map, returning an | |
(updated) system map.") | |
(stop [this system] | |
"Stops the component, using the given system map.")) | |
(defn wrap-merge-system | |
"Wraps a Lifecycle such that the input system is merged with the | |
returned system from the wrapped start implementation." | |
[lifecycle] | |
(reify Lifecycle | |
(start [_ system] | |
(merge system (start lifecycle system))) | |
(stop [_ system] | |
(stop lifecycle system)))) | |
(defn wrap-ex-info | |
"Wraps a Lifecycle such that the input system is inside an | |
ExceptionInfo wrapping a thrown exception from the wrapped start | |
implementation. The input system is available under the | |
key :input-system in the `ex-data`." | |
[lifecycle] | |
(reify Lifecycle | |
(start [_ system] | |
(try | |
(start lifecycle system) | |
(catch Throwable t | |
(if (:input-system (ex-data t)) | |
(throw t) | |
(throw (ex-info "Starting failed" {:input-system system} t)))))) | |
(stop [_ system] | |
(stop lifecycle system)))) | |
(defn combine | |
"Combines a sequence of Lifecycles into a single Lifecycle, starting | |
them in order and stopping them in reverse order. | |
It wraps the given Lifecycles with the `wrap-merge-system` and | |
`wrap-ex-info` functions." | |
[& lifecycles] | |
(reify Lifecycle | |
(start [_ system] | |
(reduce (fn [system' lifecycle] | |
(let [lifecycle' (-> lifecycle wrap-merge-system wrap-ex-info)] | |
(start lifecycle' system'))) | |
system lifecycles)) | |
(stop [_ system] | |
(doseq [lifecycle (reverse lifecycles)] | |
(stop lifecycle system))))) | |
(defn parallel | |
"Combines multiple Lifecycles into a single Lifecycle, starting and | |
stopping them in parallel. The resulting sub-systems are merged into | |
one." | |
[& lifecycles] | |
(reify Lifecycle | |
(start [_ system] | |
(->> (mapv #(future (start % system)) lifecycles) | |
(map deref) | |
(apply merge))) | |
(stop [_ system] | |
(->> (mapv #(future (stop % system)) lifecycles) | |
(mapv deref))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment