A Clojure library for setting up consistent Component-based systems
The Component Clojure library has been become an invaluable tool for Clojure developers who create applications with suites of potentially interdependent services or software that provides supporting functionality for other parts of the system. In real-world deployments, such system components often need to be started up in a particular (dependency) order, and conversely, shut down in a particular order.
The Component library has a great design: it does one thing well, completely focusing on that. However, in nearly all of my production deployments, I need more functionality, things that assist with debugging, monitoring, and fine-tuned operations. These include such things as:
start
and stop
, at the component level and at the system level.
I need to know if a system has been initialized or not; if so, has it been
started? Did it finish, and is it running? Has it been stopped, with
state data still available? Or has it been shutdown: stopped with no state
data?The code in this library is one of those things that has evolved over time and keeps getting copied and pasted into new projects, with slight updates and improvments at each new iteration. The most recent big improvements were done:
In partciular, the second one is where an API emerged (using a protocol-based approach), and this was backported to the Hexagram projects. Afterward, the code was split out into it's own project, "dev-system". Once parts of it started being used for not just development systems in the REPL, but actual production applications, more refactoring ensued and the project was renamed "system-manager".
The system-manager has three conceptual parts:
The data can be changed by its own API functions, by those of the transition
API, and of course by the high-level API as well. The data that need to be
updated are system :status
and the :system
data structure itself. Both of
these are stored in the state tracker, which is stored in the *mgr*
data
structure with the :state
key.
There are two ways to use this:
(-main)
for use in running production appsMore details on those usages are below, but first, here is more useful info:
Core/top-level API namespace: clojusc.system-manager.core
Core/top-level API public functions:
get-state
get-status
get-system-init-fn
get-system-ns
reset
restart
setup-manager
shutdown
startup
TBD
All you need to do from here on out is:
project.clj
repl
namespace in someplace like dev-resources
.repl
namespace.(startup)
, (shutdown)
,
(reset)
, etc.The REPL namespace for this project is an example of this approach; for more
insight, see dev-resources/src/clojusc/system_manager/repl.clj
.
Here's another example:
(ns myproj.dev.repl
"A development namespace for 'my project'.
Something like this can be created for any project that wishes to use the
system-manager for managing REPL state in its own development environment."
(:require
[clojusc.system-manager.core :refer :all]
[clojusc.twig :as logger]
[myproj.components.core]))
(def setup-options {
:init 'myproj.components.core/init
:after-refresh 'myproj.dev.repl/init-and-startup
:throw-errors false})
(defn init
[]
"This is used to set the options and any other global data.
This is defined in a function for re-use. For instance, when a REPL is
reloaded, the options will be lost and need to be re-applied."
(logger/set-level! '[clojusc.dev] :debug)
(setup-manager setup-options))
(defn init-and-startup
[]
"This is used as the 'after-refresh' function by the REPL tools library.
Not only do the options (and other global operations) need to be re-applied,
the system also needs to be started up, once these options have be set up."
(init)
(startup))
;; It is not always desired that a system be started up upon REPL loading.
;; Thus, we set the options and perform any global operations with `init`,
;; and let the user determine when they want to bring up (a potentially
;; computationally intensive) system.
(init)
Copyright © 2015-2018 Duncan McGreggor
Copyright © 2018 NASA
Apache License, Version 2.0.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close