Clojure Service REPL workflowλ︎
Practicalli Service REPL workflow extends the reloading concept and tools used in Practicalli REPL Reloaded workflow to Clojure Services.
Services are composed of components such as HTTP server, database connection, log publisher, message queue, request router, etc. These components can be updated by evaluating code changes as they are made, although some changes require the component or whole system to be restarted.
Lifecycle tools (Donut, Integrant, Mount, etc.) manage the components in a system, e.g.
(stop). The state of a running system can be inspected,
(system), as it is represented by a Clojure hash-map.
System Configuration as Data
Practicalli recommends expressing a system configuration as data to provide a readily understandable system.
A component may have a dependancy on one or more other components, so starting and stoping the sytem should manage components in the correct order, e.g.:
- a request router component is dependent on an http server component
- a request router is dependant on a database connection to an external data source
Using a data configuration, each component is a top-level key associated with hash-map containing the component configuration, optionally using an aero profile to support multiple environments in which the components run (e.g. development, testing, staging, production)
Aero provides tag litterals to use with an EDN configuration file to inject values based on a
#env environment variables.
Multiple configurations can be defined within the same file, i.e.
resources/config.edn, with each profile providing values for a specific environment, e.g.
System component librariesλ︎
- Mount - shared data approach using custom defstate
- donut.system - configuration as data, functions to manage components
- Integrant & Integrant REPL - configuration as data, runtime polymorphism (defmethod) to manage components, repl reloading tools
- Component - provides lifecycle protocol approach using defrecord
- Component.repl - development tools for Component