Skip to content

Instantly share code, notes, and snippets.

@tolitius
Last active January 21, 2016 06:17
Show Gist options
  • Save tolitius/a2031263ea213ec346e5 to your computer and use it in GitHub Desktop.
Save tolitius/a2031263ea213ec346e5 to your computer and use it in GitHub Desktop.

Mystique Experiment

Why

Playing around with a "system" concept, where a simple view of all the states can be created by (mount/system), and used.

This could probably be used for testing, although a simple :require does not seem all that frightening in tests.

Mutable, Whaaa!?

Yes, while a system created by (mount/system) is an immutable map, its values can be changed by starting / stopping the system: no difference from "other solutions" :), so yes lifecycle functions mutate the values in a system map. "Oh.. but in "other solutions" those are not tied to vars", ok.

This API is just a fun experiment to see whether the concept is at all useful.

Can I have multiple systems?

Not yet. It does require some work and I am still skeptical it is really useful, since most of the things you would do with more than one system could be done with Mount but differently.

However I know people asked for it, so I already built a proptotype that does it with caveats, and it might come in later, most likely under the same API (i.e. (mount/system)).

How do I subsribe to play?

This was in mount since 0.1.9-SNAPSHOT, so you most likely already have it, if not get 0.1.9-SNAPSHOT or later.

dev=> (require '[mount.core :as mount])
nil
;; creates a system map: _references_ are immutable, so it won't change after (mount/start)
dev=> (def s (mount/system))
#'dev/s
dev=> (keys s)
("app.conf/config" "app.db/conn" "app.www/nyse-app" "app.example/nrepl")
dev=> s
{"app.conf/config"
#object[mount.core.NotStartedState 0x25630070 "'#'app.conf/config' is not started (to start all the states call mount/start)"],
"app.db/conn"
#object[mount.core.NotStartedState 0x3fc45c4a "'#'app.db/conn' is not started (to start all the states call mount/start)"],
"app.www/nyse-app"
#object[mount.core.NotStartedState 0x3a082bf4 "'#'app.www/nyse-app' is not started (to start all the states call mount/start)"],
"app.example/nrepl"
#object[mount.core.NotStartedState 0x7ffa0410 "'#'app.example/nrepl' is not started (to start all the states call mount/start)"]}
nil
dev=>
dev=> (mount/start)
{:started ["#'app.conf/config" "#'app.db/conn" "#'app.www/nyse-app" "#'app.example/nrepl"]}
dev=>
;; see? did not change
dev=> s
{"app.conf/config"
#object[mount.core.NotStartedState 0x25630070 "'#'app.conf/config' is not started (to start all the states call mount/start)"],
"app.db/conn"
#object[mount.core.NotStartedState 0x3fc45c4a "'#'app.db/conn' is not started (to start all the states call mount/start)"],
"app.www/nyse-app"
#object[mount.core.NotStartedState 0x3a082bf4 "'#'app.www/nyse-app' is not started (to start all the states call mount/start)"],
"app.example/nrepl"
#object[mount.core.NotStartedState 0x7ffa0410 "'#'app.example/nrepl' is not started (to start all the states call mount/start)"]}
nil
dev=>
;; so we need to get a fresh one of off the started system
dev=> (def s (mount/system))
#'dev/s
dev=>
;; now we got a started system
dev=> s
{"app.conf/config"
{:datomic {:uri "datomic:mem://mount"},
:www {:port 4242},
:nrepl {:host "0.0.0.0", :port 7878}},
"app.db/conn"
#object[datomic.peer.LocalConnection 0x695bdc85 "datomic.peer.LocalConnection@695bdc85"],
"app.www/nyse-app"
#object[org.eclipse.jetty.server.Server 0x435263a0 "org.eclipse.jetty.server.Server@435263a0"],
"app.example/nrepl"
#clojure.tools.nrepl.server.Server{:server-socket #object[java.net.ServerSocket 0x33a40d47 "ServerSocket[addr=/0.0.0.0,localport=7878]"], :port 7878, :open-transports #object[clojure.lang.Atom 0x1e3bc33a {:status :ready, :val #{}}], :transport #object[clojure.tools.nrepl.transport$bencode 0x789dad3e "clojure.tools.nrepl.transport$bencode@789dad3e"], :greeting nil, :handler #object[clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__2859 0x686f3637 "clojure.tools.nrepl.middleware$wrap_conj_descriptor$fn__2859@686f3637"], :ss #object[java.net.ServerSocket 0x33a40d47 "ServerSocket[addr=/0.0.0.0,localport=7878]"]}}
nil
dev=>
;; just a map, so all the states are "one lookup away" :)
dev=> (s "app.www/nyse-app")
#object[org.eclipse.jetty.server.Server 0x435263a0 "org.eclipse.jetty.server.Server@435263a0"]
dev=>
dev=> (.isStarted (s "app.www/nyse-app"))
true
dev=>
dev=> (mount/stop)
{:stopped ["#'app.example/nrepl" "#'app.www/nyse-app" "#'app.db/conn"]}
dev=>
;; since references are immutable it would still point to a server instance
dev=> (s "app.www/nyse-app")
#object[org.eclipse.jetty.server.Server 0x435263a0 "org.eclipse.jetty.server.Server@435263a0"]
dev=>
;; but.. a _stopped_ server instance, since (mount/stop) stopped it
dev=> (.isStarted (s "app.www/nyse-app"))
false
dev=>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment