Skip to content

Instantly share code, notes, and snippets.

@oubiwann
Last active February 11, 2020 14:03
Show Gist options
  • Select an option

  • Save oubiwann/32a11597ea641fdb1dc6 to your computer and use it in GitHub Desktop.

Select an option

Save oubiwann/32a11597ea641fdb1dc6 to your computer and use it in GitHub Desktop.
Clojure Components Demo

demo

Clojure Components Demo

Download

$ git clone https://gist.github.com/oubiwann/32a11597ea641fdb1dc6 \
    components-demo

Usage

$ cd components-demo
$ lein trampoline run

This will generate output like the following:

Starting the system ...
    Starting HTTP server ...
    Starting DB client ...
    Starting app ...
Waiting for signal ...

If you do nothing at this point, the demo will timeout:

Giving up ...

Shutting down the system ...
    Stopping app ...
    Stopping DB client ...
    Stopping HTTP server ...

If, however, you hit ^C or send an interrupt signal after the demo app has started:

^C
Shutting down the system ...
    Stopping app ...
    Stopping DB client ...
    Stopping HTTP server ...
(ns demo
(:require [com.stuartsierra.component :as component])
(:gen-class))
(defn connect-db
"Dummy connection function."
[host port]
{:client-data "stuff"})
(defn disconnect-db
"Dummy disconnect function."
[conn])
(defrecord HTTPServer [host port]
component/Lifecycle
(start [component]
(println "\tStarting HTTP server ...")
component)
(stop [component]
(println "\tStopping HTTP server ...")
component))
(defn new-http-server [host port]
(map->HTTPServer {:host host :port port}))
(defrecord Database [host port conn]
component/Lifecycle
(start [component]
(println "\tStarting DB client ...")
(let [conn (connect-db host port)]
(assoc component :conn conn)))
(stop [component]
(println "\tStopping DB client ...")
(disconnect-db conn)
(assoc component :conn nil)))
(defn new-db-connection [host port]
(map->Database {:host host :port port}))
(defrecord App [cfg db httpd]
component/Lifecycle
(start [component]
(println "\tStarting app ...")
component)
(stop [component]
(println "\tStopping app ...")
component))
(defn new-app [cfg]
(map->App {:cfg cfg}))
(defn demo-system [cfg]
(component/system-map
:db (new-db-connection (get-in cfg [:db :host])
(get-in cfg [:db :port]))
:httpd (new-http-server (get-in cfg [:http :listen])
(get-in cfg [:http :port]))
:app (component/using
(new-app cfg)
[:httpd :db])))
(defn init [sys]
(println "Starting the system ...")
(component/start sys))
(defn shutdown [sys]
(println "\nShutting down the system ...")
(component/stop sys))
(defn -main
[& args]
(let [sys (demo-system {:httpd {:listen "127.0.0.1"
:port 8080}
:db {:host "127.0.0.1"
:port 9090}})]
(init sys)
(.addShutdownHook (Runtime/getRuntime)
(Thread. #(shutdown sys)))
(println "Waiting for signal ...")
(Thread/sleep 30000)
(println "Giving up ...")))
(defproject demo "0.1.0"
:description "Clojure Components Demo"
:url "https://gist.github.com/oubiwann/32a11597ea641fdb1dc6"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.7.0"]
[com.stuartsierra/component "0.3.0"]]
:source-paths ["."]
:main ^:skip-aot demo
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment