Merge branch '0.1.7'
Conflicts: .gitignore src/mount/core.cljc
This commit is contained in:
commit
a4dfe74c66
37 changed files with 479 additions and 212 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -7,6 +7,7 @@ pom.xml.asc
|
|||
dev/resources/public/js/*
|
||||
figwheel_server.log
|
||||
build.xml
|
||||
doo-index.html
|
||||
*.jar
|
||||
*.class
|
||||
/.lein-*
|
||||
|
|
|
|||
108
build.boot
Normal file
108
build.boot
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
(set-env!
|
||||
:source-paths #{"src"}
|
||||
:dependencies '[;; mount brings _no dependencies_, everything here is for
|
||||
;; mount dev, examples apps and tests
|
||||
|
||||
[org.clojure/clojure "1.7.0" :scope "provided"]
|
||||
[org.clojure/clojurescript "1.7.189" :scope "provided" :classifier "aot"]
|
||||
[datascript "0.13.3" :scope "provided"]
|
||||
[compojure "1.4.0" :scope "provided"]
|
||||
[ring/ring-jetty-adapter "1.1.0" :scope "provided"]
|
||||
[cheshire "5.5.0" :scope "provided"]
|
||||
[hiccups "0.3.0" :scope "provided" :exclusions [org.clojure/clojurescript]]
|
||||
[com.andrewmcveigh/cljs-time "0.3.14" :scope "provided"]
|
||||
[ch.qos.logback/logback-classic "1.1.3" :scope "provided"]
|
||||
[org.clojure/tools.logging "0.3.1" :scope "provided"]
|
||||
[robert/hooke "1.3.0" :scope "provided"]
|
||||
[org.clojure/tools.namespace "0.2.11" :scope "provided"]
|
||||
[org.clojure/tools.nrepl "0.2.12" :scope "provided"]
|
||||
[com.datomic/datomic-free "0.9.5327" :scope "provided" :exclusions [joda-time]]
|
||||
|
||||
;; boot clj
|
||||
[boot/core "2.5.1" :scope "provided"]
|
||||
[adzerk/bootlaces "0.1.13" :scope "test"]
|
||||
[adzerk/boot-logservice "1.0.1" :scope "test"]
|
||||
[adzerk/boot-test "1.0.6" :scope "test"]
|
||||
|
||||
;; boot cljs
|
||||
[adzerk/boot-cljs "1.7.170-3" :scope "test"]
|
||||
[adzerk/boot-cljs-repl "0.3.0" :scope "test"]
|
||||
[pandeiro/boot-http "0.7.1-SNAPSHOT" :scope "test"]
|
||||
[com.cemerick/piggieback "0.2.1" :scope "test" :exclusions [org.clojure/clojurescript]]
|
||||
[weasel "0.7.0" :scope "test" :exclusions [org.clojure/clojurescript]]
|
||||
[adzerk/boot-reload "0.4.2" :scope "test"]
|
||||
[crisptrutski/boot-cljs-test "0.2.1-SNAPSHOT" :scope "test"]])
|
||||
|
||||
(require '[adzerk.bootlaces :refer :all]
|
||||
'[adzerk.boot-test :as bt]
|
||||
'[adzerk.boot-logservice :as log-service]
|
||||
'[adzerk.boot-cljs :refer [cljs]]
|
||||
'[adzerk.boot-cljs-repl :refer [cljs-repl start-repl]]
|
||||
'[adzerk.boot-reload :refer [reload]]
|
||||
'[pandeiro.boot-http :refer :all]
|
||||
'[crisptrutski.boot-cljs-test :as tcs]
|
||||
'[clojure.tools.logging :as log]
|
||||
'[clojure.tools.namespace.repl :refer [set-refresh-dirs]])
|
||||
|
||||
(def +version+ "0.1.7-SNAPSHOT")
|
||||
|
||||
(bootlaces! +version+)
|
||||
|
||||
(def log4b
|
||||
[:configuration
|
||||
[:appender {:name "STDOUT" :class "ch.qos.logback.core.ConsoleAppender"}
|
||||
[:encoder [:pattern "%-5level %logger{36} - %msg%n"]]]
|
||||
[:root {:level "TRACE"}
|
||||
[:appender-ref {:ref "STDOUT"}]]])
|
||||
|
||||
(deftask dev []
|
||||
(set-env! :source-paths #(conj % "dev/clj" "dev/cljs"))
|
||||
|
||||
(alter-var-root #'log/*logger-factory*
|
||||
(constantly (log-service/make-factory log4b)))
|
||||
(apply set-refresh-dirs (get-env :directories))
|
||||
(load-data-readers!)
|
||||
|
||||
(require 'dev)
|
||||
(in-ns 'dev))
|
||||
|
||||
(deftask test []
|
||||
(set-env! :source-paths #(conj % "test/core" "test/clj")) ;; (!) :source-paths must not overlap.
|
||||
(bt/test))
|
||||
|
||||
(deftask test-cljs []
|
||||
(set-env! :source-paths #(conj % "test/core" "test/cljs"))
|
||||
(set-env! :resource-paths #{"test/resources"})
|
||||
|
||||
(comp
|
||||
(tcs/test-cljs ;; :optimizations :advanced
|
||||
:out-file "mount.js")))
|
||||
|
||||
(deftask test-cljs-advanced []
|
||||
(set-env! :source-paths #(conj % "dev/clj" "dev/cljs"))
|
||||
(set-env! :resource-paths #{"dev/resources"})
|
||||
|
||||
(comp
|
||||
(cljs :optimizations :advanced :ids #{"mount"})))
|
||||
|
||||
(deftask cljs-example
|
||||
"mount cljs example"
|
||||
[]
|
||||
(set-env! :source-paths #(conj % "dev/clj" "dev/cljs"))
|
||||
(set-env! :resource-paths #{"dev/resources"})
|
||||
|
||||
(comp
|
||||
(wait)
|
||||
(serve :dir "dev/resources/public/")
|
||||
(cljs-repl)
|
||||
(cljs :optimizations :advanced :ids #{"mount"})))
|
||||
|
||||
(task-options!
|
||||
push #(-> (into {} %) (assoc :ensure-branch nil))
|
||||
pom {:project 'mount
|
||||
:version +version+
|
||||
:description "managing Clojure and ClojureScript app state since (reset)"
|
||||
:url "https://github.com/tolitius/mount"
|
||||
:scm {:url "https://github.com/tolitius/mount"}
|
||||
:license {"Eclipse Public License"
|
||||
"http://www.eclipse.org/legal/epl-v10.html"}})
|
||||
11
circle.yml
11
circle.yml
|
|
@ -2,9 +2,14 @@ machine:
|
|||
java:
|
||||
version: oraclejdk8
|
||||
|
||||
dependencies:
|
||||
pre:
|
||||
- wget https://github.com/boot-clj/boot-bin/releases/download/2.4.2/boot.sh
|
||||
- mv boot.sh boot && chmod a+x boot && sudo mv boot /usr/local/bin
|
||||
|
||||
test:
|
||||
override:
|
||||
- lein do clean, test
|
||||
- lein do clean, doo phantom test once
|
||||
- lein do clean, cljsbuild once prod
|
||||
- boot test
|
||||
- boot test-cljs
|
||||
- boot test-cljs-advanced
|
||||
- lein test2junit
|
||||
|
|
|
|||
50
dev/clj/app/db.clj
Normal file
50
dev/clj/app/db.clj
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
(ns app.db
|
||||
(:require [mount.core :refer [defstate]]
|
||||
[datomic.api :as d]
|
||||
[clojure.tools.logging :refer [info]]
|
||||
[app.conf :refer [config]]))
|
||||
|
||||
(defn- new-connection [conf]
|
||||
(info "conf: " conf)
|
||||
(let [uri (get-in conf [:datomic :uri])]
|
||||
(info "creating a connection to datomic:" uri)
|
||||
(d/create-database uri)
|
||||
(d/connect uri)))
|
||||
|
||||
(defn disconnect [conf conn]
|
||||
(let [uri (get-in conf [:datomic :uri])]
|
||||
(info "disconnecting from " uri)
|
||||
(.release conn) ;; usually it's not released, here just to illustrate the access to connection on (stop)
|
||||
(d/delete-database uri)))
|
||||
|
||||
(defstate conn :start (new-connection config)
|
||||
:stop (disconnect config conn))
|
||||
|
||||
;; datomic schema (staging as an example)
|
||||
(defn create-schema [conn]
|
||||
(let [schema [{:db/id #db/id [:db.part/db]
|
||||
:db/ident :order/symbol
|
||||
:db/valueType :db.type/string
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db/index true
|
||||
:db.install/_attribute :db.part/db}
|
||||
|
||||
{:db/id #db/id [:db.part/db]
|
||||
:db/ident :order/bid
|
||||
:db/valueType :db.type/bigdec
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db.install/_attribute :db.part/db}
|
||||
|
||||
{:db/id #db/id [:db.part/db]
|
||||
:db/ident :order/qty
|
||||
:db/valueType :db.type/long
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db.install/_attribute :db.part/db}
|
||||
|
||||
{:db/id #db/id [:db.part/db]
|
||||
:db/ident :order/offer
|
||||
:db/valueType :db.type/bigdec
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db.install/_attribute :db.part/db}]]
|
||||
|
||||
@(d/transact conn schema)))
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
(ns app.example
|
||||
(:require [datomic.api :as d]
|
||||
[clojure.tools.nrepl.server :refer [start-server stop-server]]
|
||||
(:require [clojure.tools.nrepl.server :refer [start-server stop-server]]
|
||||
[mount.core :as mount :refer [defstate]]
|
||||
[app.utils.datomic :refer [touch]]
|
||||
[app.conf :refer [config]]
|
||||
[app.nyse :as nyse]))
|
||||
[app.www])
|
||||
(:gen-class)) ;; for -main / uberjar (no need in dev)
|
||||
|
||||
;; example on creating a network REPL
|
||||
(defn- start-nrepl [{:keys [host port]}]
|
||||
|
|
@ -14,52 +13,6 @@
|
|||
(defstate nrepl :start (start-nrepl (:nrepl config))
|
||||
:stop (stop-server nrepl))
|
||||
|
||||
;; datomic schema
|
||||
(defn create-schema [conn]
|
||||
(let [schema [{:db/id #db/id [:db.part/db]
|
||||
:db/ident :order/symbol
|
||||
:db/valueType :db.type/string
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db/index true
|
||||
:db.install/_attribute :db.part/db}
|
||||
|
||||
{:db/id #db/id [:db.part/db]
|
||||
:db/ident :order/bid
|
||||
:db/valueType :db.type/bigdec
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db.install/_attribute :db.part/db}
|
||||
|
||||
{:db/id #db/id [:db.part/db]
|
||||
:db/ident :order/qty
|
||||
:db/valueType :db.type/long
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db.install/_attribute :db.part/db}
|
||||
|
||||
{:db/id #db/id [:db.part/db]
|
||||
:db/ident :order/offer
|
||||
:db/valueType :db.type/bigdec
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db.install/_attribute :db.part/db}]]
|
||||
|
||||
@(d/transact conn schema)))
|
||||
|
||||
(defn add-order [ticker bid offer qty] ;; can take connection as param
|
||||
@(d/transact nyse/conn [{:db/id (d/tempid :db.part/user)
|
||||
:order/symbol ticker
|
||||
:order/bid bid
|
||||
:order/offer offer
|
||||
:order/qty qty}]))
|
||||
|
||||
|
||||
(defn find-orders [ticker] ;; can take connection as param
|
||||
(let [orders (d/q '[:find ?e :in $ ?ticker
|
||||
:where [?e :order/symbol ?ticker]]
|
||||
(d/db nyse/conn) ticker)]
|
||||
(touch nyse/conn orders)))
|
||||
|
||||
(defn create-nyse-schema []
|
||||
(create-schema nyse/conn))
|
||||
|
||||
;; example of an app entry point
|
||||
(defn -main [& args]
|
||||
(mount/start))
|
||||
|
|
|
|||
|
|
@ -1,21 +1,20 @@
|
|||
(ns app.nyse
|
||||
(:require [mount.core :as mount :refer [defstate]]
|
||||
[datomic.api :as d]
|
||||
[clojure.tools.logging :refer [info]]
|
||||
[app.conf :refer [config]]))
|
||||
(:require [datomic.api :as d]
|
||||
[app.db :refer [create-schema] :as db]
|
||||
[app.utils.datomic :refer [touch]]))
|
||||
|
||||
(defn- new-connection [conf]
|
||||
(info "conf: " conf)
|
||||
(let [uri (get-in conf [:datomic :uri])]
|
||||
(info "creating a connection to datomic:" uri)
|
||||
(d/create-database uri)
|
||||
(d/connect uri)))
|
||||
(defn add-order [ticker bid offer qty] ;; can take connection as param
|
||||
@(d/transact db/conn [{:db/id (d/tempid :db.part/user)
|
||||
:order/symbol ticker
|
||||
:order/bid bid
|
||||
:order/offer offer
|
||||
:order/qty qty}]))
|
||||
|
||||
(defn disconnect [conf conn]
|
||||
(let [uri (get-in conf [:datomic :uri])]
|
||||
(info "disconnecting from " uri)
|
||||
(.release conn) ;; usually it's not released, here just to illustrate the access to connection on (stop)
|
||||
(d/delete-database uri)))
|
||||
(defn find-orders [ticker] ;; can take connection as param
|
||||
(let [orders (d/q '[:find ?e :in $ ?ticker
|
||||
:where [?e :order/symbol ?ticker]]
|
||||
(d/db db/conn) ticker)]
|
||||
(touch db/conn orders)))
|
||||
|
||||
(defstate conn :start (new-connection config)
|
||||
:stop (disconnect config conn))
|
||||
(defn create-nyse-schema []
|
||||
(create-schema db/conn))
|
||||
|
|
|
|||
31
dev/clj/app/www.clj
Normal file
31
dev/clj/app/www.clj
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
(ns app.www
|
||||
(:require [app.nyse :refer [add-order find-orders create-nyse-schema]]
|
||||
[app.conf :refer [config]]
|
||||
[mount.core :refer [defstate]]
|
||||
[cheshire.core :refer [generate-string]]
|
||||
[compojure.core :refer [routes defroutes GET POST]]
|
||||
[compojure.handler :as handler]
|
||||
[ring.adapter.jetty :refer [run-jetty]]))
|
||||
|
||||
(defroutes mount-example-routes
|
||||
|
||||
(GET "/" [] "welcome to mount sample app!")
|
||||
(GET "/nyse/orders/:ticker" [ticker]
|
||||
(generate-string (find-orders ticker)))
|
||||
|
||||
(POST "/nyse/orders" [ticker qty bid offer]
|
||||
(add-order ticker (bigdec bid) (bigdec offer) (Integer/parseInt qty))
|
||||
(generate-string {:added {:ticker ticker
|
||||
:qty qty
|
||||
:bid bid
|
||||
:offer offer}})))
|
||||
|
||||
(defn start-nyse [{:keys [www]}]
|
||||
(create-nyse-schema) ;; creating schema (usually done long before the app is started..)
|
||||
(-> (routes mount-example-routes)
|
||||
(handler/site)
|
||||
(run-jetty {:join? false
|
||||
:port (:port www)})))
|
||||
|
||||
(defstate nyse-app :start (start-nyse config)
|
||||
:stop (.stop nyse-app)) ;; it's a "org.eclipse.jetty.server.Server" at this point
|
||||
|
|
@ -1,23 +1,18 @@
|
|||
(ns dev
|
||||
"Tools for interactive development with the REPL. This file should
|
||||
not be included in a production build of the application."
|
||||
(:require [clojure.java.io :as io]
|
||||
[clojure.java.javadoc :refer [javadoc]]
|
||||
[clojure.pprint :refer [pprint]]
|
||||
[clojure.reflect :refer [reflect]]
|
||||
[clojure.repl :refer [apropos dir doc find-doc pst source]]
|
||||
[clojure.set :as set]
|
||||
[clojure.string :as str]
|
||||
[clojure.test :as test]
|
||||
(:require [clojure.pprint :refer [pprint]]
|
||||
[clojure.tools.namespace.repl :as tn]
|
||||
[boot.core :refer [load-data-readers!]]
|
||||
[mount.core :as mount]
|
||||
[app.utils.logging :refer [with-logging-status]]
|
||||
[app.example :refer [create-nyse-schema find-orders add-order]])) ;; <<<< replace this your "app" namespace(s) you want to be available at REPL time
|
||||
[app.www]
|
||||
[app.example]
|
||||
[app.nyse :refer [create-nyse-schema find-orders add-order]])) ;; <<<< replace this your "app" namespace(s) you want to be available at REPL time
|
||||
|
||||
(defn start []
|
||||
(with-logging-status)
|
||||
(mount/start #'app.conf/config
|
||||
#'app.nyse/conn
|
||||
#'app.db/conn
|
||||
#'app.www/nyse-app
|
||||
#'app.example/nrepl)) ;; example on how to start app with certain states
|
||||
|
||||
(defn stop []
|
||||
|
|
@ -44,3 +39,4 @@
|
|||
(tn/refresh :after 'dev/go))
|
||||
|
||||
(mount/in-clj-mode)
|
||||
(load-data-readers!)
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
{:datomic
|
||||
{:uri "datomic:mem://mount"}
|
||||
|
||||
:www {:port 4242}
|
||||
|
||||
:h2
|
||||
{:classname "org.h2.Driver"
|
||||
:subprotocol "h2"
|
||||
|
|
|
|||
1
dev/resources/mount.cljs.edn
Normal file
1
dev/resources/mount.cljs.edn
Normal file
|
|
@ -0,0 +1 @@
|
|||
{:require [app.example]}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<script src="js/compiled/mount.js" type="text/javascript"></script>
|
||||
<script src="../mount.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
13
project.clj
13
project.clj
|
|
@ -1,5 +1,5 @@
|
|||
(defproject mount "0.1.6"
|
||||
:description "managing Clojure app state since (reset)"
|
||||
(defproject mount "0.1.7-SNAPSHOT"
|
||||
:description "managing Clojure and ClojureScript app state since (reset)"
|
||||
:url "https://github.com/tolitius/mount"
|
||||
:license {:name "Eclipse Public License"
|
||||
:url "http://www.eclipse.org/legal/epl-v10.html"}
|
||||
|
|
@ -8,10 +8,13 @@
|
|||
|
||||
:dependencies [] ;; for visual clarity
|
||||
|
||||
:profiles {:dev {:source-paths ["dev" "dev/clj"]
|
||||
:profiles {:dev {:source-paths ["dev" "dev/clj" "test/clj"]
|
||||
:dependencies [[org.clojure/clojure "1.7.0"]
|
||||
[org.clojure/clojurescript "1.7.170"]
|
||||
[org.clojure/clojurescript "1.7.170"]; :classifier "aot"]
|
||||
[datascript "0.13.3"]
|
||||
[compojure "1.4.0"]
|
||||
[ring/ring-jetty-adapter "1.1.0"]
|
||||
[cheshire "5.5.0"]
|
||||
[hiccups "0.3.0"]
|
||||
[com.andrewmcveigh/cljs-time "0.3.14"]
|
||||
[ch.qos.logback/logback-classic "1.1.3"]
|
||||
|
|
@ -58,4 +61,4 @@
|
|||
:optimizations :advanced
|
||||
:pretty-print false}}}}}
|
||||
|
||||
:test {:source-paths ["dev" "test/clj" "test"]}})
|
||||
:test {:source-paths ["test/core" "test/clj" "test/cljs"]}})
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
(ns mount.core
|
||||
#?(:clj (:require [mount.tools.macro :refer [on-error throw-runtime] :as macro])
|
||||
:cljs (:require [mount.tools.macro :as macro]
|
||||
[mount.tools.cljs :as cljs]))
|
||||
#?(:cljs (:require-macros [mount.tools.macro :refer [on-error throw-runtime]])))
|
||||
:cljs (:require [mount.tools.macro :as macro]))
|
||||
#?(:cljs (:require-macros [mount.core]
|
||||
[mount.tools.macro :refer [on-error throw-runtime]])))
|
||||
|
||||
(defonce ^:private -args (atom :no-args)) ;; mostly for command line args and external files
|
||||
(defonce ^:private state-seq (atom 0))
|
||||
|
|
@ -34,13 +34,12 @@
|
|||
(str "#'" ns "/" name))
|
||||
|
||||
(defn- pounded? [f]
|
||||
(let [pound "(fn* [] "] ;;TODO: think of a better (i.e. typed) way to distinguish #(f params) from (fn [params] (...)))
|
||||
#?(:clj (.startsWith (str f) pound)
|
||||
:cljs (cljs/starts-with? (str f) pound))))
|
||||
(let [pound "(fn* [] "] ;;TODO: think of a better (i.e. typed) way to distinguish #(f params) from (fn [params] (...)))
|
||||
(.startsWith (str f) pound)))
|
||||
|
||||
(defn unpound [f]
|
||||
(if (pounded? f)
|
||||
(nth f 2) ;; magic 2 is to get the body => ["fn*" "[]" "(fn body)"]
|
||||
(nth f 2) ;; magic 2 is to get the body => ["fn*" "[]" "(fn body)"]
|
||||
f))
|
||||
|
||||
(defn- cleanup-if-dirty
|
||||
|
|
@ -50,29 +49,30 @@
|
|||
it is meant to be called by defstate before defining a new state"
|
||||
[state]
|
||||
(when-let [stop (@running state)]
|
||||
(prn (str "<< stopping.. " state " (namespace was recompiled)"))
|
||||
(stop)
|
||||
(swap! running dissoc state)))
|
||||
|
||||
#?(:clj
|
||||
(defn current-state [state]
|
||||
(let [{:keys [inst var]} (@meta-state state)]
|
||||
(if (= @mode :cljc)
|
||||
@inst
|
||||
(var-get var))))
|
||||
(defn current-state [state]
|
||||
(let [{:keys [inst var]} (@meta-state state)]
|
||||
(if (= @mode :cljc)
|
||||
@inst
|
||||
(var-get var))))
|
||||
|
||||
:cljs
|
||||
(defn current-state [state]
|
||||
(-> (@meta-state state) :inst deref)))
|
||||
(defn current-state [state]
|
||||
(-> (@meta-state state) :inst deref)))
|
||||
|
||||
#?(:clj
|
||||
(defn alter-state! [{:keys [var inst]} value]
|
||||
(if (= @mode :cljc)
|
||||
(reset! inst value)
|
||||
(alter-var-root var (constantly value))))
|
||||
(defn alter-state! [{:keys [var inst]} value]
|
||||
(if (= @mode :cljc)
|
||||
(reset! inst value)
|
||||
(alter-var-root var (constantly value))))
|
||||
|
||||
:cljs
|
||||
(defn alter-state! [{:keys [inst]} value]
|
||||
(reset! inst value)))
|
||||
(defn alter-state! [{:keys [inst]} value]
|
||||
(reset! inst value)))
|
||||
|
||||
(defn- update-meta! [path v]
|
||||
(swap! meta-state assoc-in path v))
|
||||
|
|
@ -127,26 +127,35 @@
|
|||
(up name state (atom #{})))
|
||||
@inst)))
|
||||
|
||||
(defmacro defstate [state & body]
|
||||
(let [[state params] (macro/name-with-attributes state body)
|
||||
{:keys [start stop suspend resume] :as lifecycle} (apply hash-map params)
|
||||
state-name (with-ns #?(:clj *ns*
|
||||
:cljs (cljs/this-ns)) state) ;; on cljs side (cljs.analyzer/*cljs-ns*) may do it, but still might not be good for :advanced
|
||||
order (make-state-seq state-name)
|
||||
sym (str state)]
|
||||
(validate lifecycle)
|
||||
(cleanup-if-dirty state-name)
|
||||
(let [s-meta (cond-> {:order order
|
||||
:start `(fn [] ~start)
|
||||
:status #{:stopped}}
|
||||
stop (assoc :stop `(fn [] ~stop))
|
||||
suspend (assoc :suspend `(fn [] ~suspend))
|
||||
resume (assoc :resume `(fn [] ~resume)))]
|
||||
`(do
|
||||
(def ~state (DerefableState. ~state-name))
|
||||
((var update-meta!) [~state-name] (assoc ~s-meta :inst (atom (NotStartedState. ~state-name))
|
||||
:var (var ~state)))
|
||||
(var ~state)))))
|
||||
#?(:clj
|
||||
(defmacro defstate [state & body]
|
||||
(let [[state params] (macro/name-with-attributes state body)
|
||||
{:keys [start stop suspend resume] :as lifecycle} (apply hash-map params)
|
||||
state-name (with-ns *ns* state)
|
||||
order (make-state-seq state-name)
|
||||
sym (str state)]
|
||||
(validate lifecycle)
|
||||
(cleanup-if-dirty state-name)
|
||||
(let [s-meta (cond-> {:order order
|
||||
:start `(fn [] ~start)
|
||||
:status #{:stopped}}
|
||||
stop (assoc :stop `(fn [] ~stop))
|
||||
suspend (assoc :suspend `(fn [] ~suspend))
|
||||
resume (assoc :resume `(fn [] ~resume)))]
|
||||
`(do
|
||||
(def ~state (DerefableState. ~state-name))
|
||||
((var mount.core/update-meta!) [~state-name] (assoc ~s-meta :inst (atom (NotStartedState. ~state-name))
|
||||
:var (var ~state)))
|
||||
(var ~state))))))
|
||||
|
||||
#?(:clj
|
||||
(defmacro defstate! [state & {:keys [start! stop!]}]
|
||||
(let [state-name (with-ns *ns* state)]
|
||||
`(defstate ~state
|
||||
:start (~'let [~state (mount/current-state ~state-name)]
|
||||
~start!)
|
||||
:stop (~'let [~state (mount/current-state ~state-name)]
|
||||
~stop!)))))
|
||||
|
||||
(defn in-cljc-mode []
|
||||
(reset! mode :cljc))
|
||||
|
|
@ -182,7 +191,7 @@
|
|||
|
||||
#?(:cljs
|
||||
(defn var-to-str [v]
|
||||
(if (var? v)
|
||||
(if (instance? cljs.core.Var v)
|
||||
(let [{:keys [ns name]} (meta v)]
|
||||
(with-ns ns name))
|
||||
v)))
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
(ns mount.tools.cljs
|
||||
(:require [cljs.analyzer :as ana]
|
||||
[goog.string :as gstring]))
|
||||
|
||||
(defn this-ns []
|
||||
ana/*cljs-ns*)
|
||||
|
||||
(defn starts-with? [s pre]
|
||||
(gstring/startsWith s pre))
|
||||
|
|
@ -1,16 +1,19 @@
|
|||
(ns mount.tools.macro)
|
||||
(ns mount.tools.macro
|
||||
#?(:cljs (:require-macros [mount.tools.macro])))
|
||||
|
||||
(defmacro on-error [msg f]
|
||||
`(try
|
||||
~f
|
||||
(catch #?(:clj Throwable
|
||||
:cljs :default) t#
|
||||
(throw #?(:clj (RuntimeException. ~msg t#)
|
||||
:cljs (js/Error (str ~msg (.-stack t#))))))))
|
||||
#?(:clj
|
||||
(defmacro on-error [msg f]
|
||||
`(try
|
||||
~f
|
||||
(catch #?(:clj Throwable
|
||||
:cljs :default) t#
|
||||
(throw #?(:clj (RuntimeException. ~msg t#)
|
||||
:cljs (js/Error (str ~msg (.-stack t#)))))))))
|
||||
|
||||
(defmacro throw-runtime [msg]
|
||||
`(throw #?(:clj (RuntimeException. ~msg)
|
||||
:cljs (js/Error (str ~msg)))))
|
||||
#?(:clj
|
||||
(defmacro throw-runtime [msg]
|
||||
`(throw #?(:clj (RuntimeException. ~msg)
|
||||
:cljs (js/Error (str ~msg))))))
|
||||
|
||||
;; this is a one to one copy from https://github.com/clojure/tools.macro
|
||||
;; to avoid a lib dependency for a single function
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
(ns app.conf
|
||||
(ns tapp.conf
|
||||
(:require [mount.core :as mount :refer [defstate]]
|
||||
[clojure.edn :as edn]
|
||||
[clojure.tools.logging :refer [info]]))
|
||||
|
||||
(alter-meta! *ns* assoc ::load false)
|
||||
|
||||
(defn load-config [path]
|
||||
(info "loading config from" path)
|
||||
(-> path
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
(ns app.example
|
||||
(ns tapp.example
|
||||
(:require [datomic.api :as d]
|
||||
[clojure.tools.nrepl.server :refer [start-server stop-server]]
|
||||
[mount.core :as mount :refer [defstate]]
|
||||
[app.utils.datomic :refer [touch]]
|
||||
[app.conf :refer [config]]
|
||||
[app.nyse :as nyse]))
|
||||
[tapp.utils.datomic :refer [touch]]
|
||||
[tapp.conf :refer [config]]
|
||||
[tapp.nyse :as nyse]))
|
||||
|
||||
(alter-meta! *ns* assoc ::load false)
|
||||
|
||||
;; example on creating a network REPL
|
||||
(defn- start-nrepl [{:keys [host port]}]
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
(ns app.nyse
|
||||
(ns tapp.nyse
|
||||
(:require [mount.core :as mount :refer [defstate]]
|
||||
[datomic.api :as d]
|
||||
[clojure.tools.logging :refer [info]]
|
||||
[app.conf :refer [config]]))
|
||||
[tapp.conf :refer [config]]))
|
||||
|
||||
(alter-meta! *ns* assoc ::load false)
|
||||
|
||||
(defn- new-connection [conf]
|
||||
(info "conf: " conf)
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
(ns app.utils.datomic
|
||||
(ns tapp.utils.datomic
|
||||
(:require [datomic.api :as d]))
|
||||
|
||||
(alter-meta! *ns* assoc ::load false)
|
||||
|
||||
(defn entity [conn id]
|
||||
(d/entity (d/db conn) id))
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
(ns app.utils.logging ;; << change to your namespace/path
|
||||
(ns tapp.utils.logging ;; << change to your namespace/path
|
||||
(:require [mount.core]
|
||||
[robert.hooke :refer [add-hook clear-hooks]]
|
||||
[clojure.string :refer [split]]
|
||||
25
test/cljs/tapp/audit_log.cljs
Normal file
25
test/cljs/tapp/audit_log.cljs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
(ns tapp.audit-log
|
||||
(:require [datascript.core :as d]
|
||||
[cljs-time.core :refer [now]])
|
||||
(:require-macros [mount.core :refer [defstate]]))
|
||||
|
||||
(defstate log :start (d/create-conn {}))
|
||||
|
||||
(defn audit [db source & msg]
|
||||
(d/transact! @db [{:db/id -1
|
||||
:source source
|
||||
:timestamp (now)
|
||||
:msg (apply str msg)}]))
|
||||
|
||||
(defn find-source-logs [db source]
|
||||
(d/q '{:find [?t ?msg]
|
||||
:in [$ ?s]
|
||||
:where [[?e :source ?s]
|
||||
[?e :timestamp ?t]
|
||||
[?e :msg ?msg]]}
|
||||
@@db source))
|
||||
|
||||
(defn find-all-logs [db]
|
||||
(->> (map :e (d/datoms @@db :aevt :timestamp))
|
||||
dedupe
|
||||
(d/pull-many @@db '[:timestamp :source :msg])))
|
||||
9
test/cljs/tapp/conf.cljs
Normal file
9
test/cljs/tapp/conf.cljs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
(ns tapp.conf
|
||||
(:require [tapp.audit-log :refer [audit log]])
|
||||
(:require-macros [mount.core :refer [defstate]]))
|
||||
|
||||
(defn load-config [path]
|
||||
(audit log :app-conf "loading config from '" path "' (at least pretending)")
|
||||
{:system-a {:uri "ws://echo.websocket.org/"}})
|
||||
|
||||
(defstate config :start (load-config "resources/config.end"))
|
||||
26
test/cljs/tapp/example.cljs
Normal file
26
test/cljs/tapp/example.cljs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
(ns tapp.example
|
||||
(:require [mount.core :as mount]
|
||||
[tapp.conf]
|
||||
[tapp.websockets]
|
||||
[tapp.audit-log :refer [log find-all-logs]]
|
||||
[cljs-time.format :refer [unparse formatters]]
|
||||
[hiccups.runtime :as hiccupsrt])
|
||||
(:require-macros [hiccups.core :as hiccups :refer [html]]))
|
||||
|
||||
(defn format-log-event [{:keys [timestamp source msg]}]
|
||||
(str (unparse (formatters :date-hour-minute-second-fraction) timestamp)
|
||||
" → [" (name source) "]: " msg))
|
||||
|
||||
(defn show-log []
|
||||
(.write js/document
|
||||
(html [:ul (doall (for [e (find-all-logs log)]
|
||||
[:li (format-log-event e)]))])))
|
||||
|
||||
(mount/start)
|
||||
|
||||
;; time to establish a websocket connection before disconnecting
|
||||
(js/setTimeout #(mount/stop-except "#'tapp.audit-log/log") 500)
|
||||
|
||||
;; time to close a connection to show it in audit
|
||||
(js/setTimeout #(show-log) 1000)
|
||||
|
||||
22
test/cljs/tapp/websockets.cljs
Normal file
22
test/cljs/tapp/websockets.cljs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
(ns tapp.websockets
|
||||
(:require [tapp.conf :refer [config]]
|
||||
[tapp.audit-log :refer [audit log]])
|
||||
(:require-macros [mount.core :refer [defstate]]))
|
||||
|
||||
(defn ws-status [ws]
|
||||
{:url (.-url ws) :ready-state (.-readyState ws)})
|
||||
|
||||
(defn connect [uri]
|
||||
(let [ws (js/WebSocket. uri)]
|
||||
(audit log :system-a "connecting to " (ws-status ws))
|
||||
(set! (.-onopen ws) #(audit log :system-a "opened " (ws-status ws)))
|
||||
(set! (.-onclose ws) #(audit log :system-a "closed " (ws-status ws)))
|
||||
ws))
|
||||
|
||||
(defn disconnect [ws]
|
||||
(audit log :system-a "closing " (ws-status @ws))
|
||||
(.close @ws)
|
||||
(audit log :system-a "disconnecting " (ws-status @ws)))
|
||||
|
||||
(defstate system-a :start (connect (get-in @config [:system-a :uri]))
|
||||
:stop (disconnect system-a))
|
||||
|
|
@ -15,6 +15,8 @@
|
|||
mount.test.suspend-resume
|
||||
))
|
||||
|
||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||
|
||||
(mount.core/in-cljc-mode)
|
||||
|
||||
#?(:cljs
|
||||
|
|
@ -2,23 +2,25 @@
|
|||
(:require
|
||||
#?@(:cljs [[cljs.test :as t :refer-macros [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer-macros [defstate]]
|
||||
[app.websockets :refer [system-a]]
|
||||
[app.conf :refer [config]]
|
||||
[app.audit-log :refer [log]]]
|
||||
[tapp.websockets :refer [system-a]]
|
||||
[tapp.conf :refer [config]]
|
||||
[tapp.audit-log :refer [log]]]
|
||||
:clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer [defstate]]
|
||||
[app.example]])
|
||||
[tapp.example]])
|
||||
[mount.test.helper :refer [dval helper forty-two]]))
|
||||
|
||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||
|
||||
#?(:clj
|
||||
(deftest cleanup-dirty-states
|
||||
(let [_ (mount/start)]
|
||||
(is (not (.isClosed (:server-socket (dval app.example/nrepl)))))
|
||||
(require 'app.example :reload)
|
||||
(is (not (.isClosed (:server-socket (dval tapp.example/nrepl)))))
|
||||
(require 'tapp.example :reload)
|
||||
(mount/start) ;; should not result in "BindException Address already in use" since the clean up will stop the previous instance
|
||||
(is (not (.isClosed (:server-socket (dval app.example/nrepl)))))
|
||||
(is (not (.isClosed (:server-socket (dval tapp.example/nrepl)))))
|
||||
(mount/stop)
|
||||
(is (instance? mount.core.NotStartedState (dval app.example/nrepl))))))
|
||||
(is (instance? mount.core.NotStartedState (dval tapp.example/nrepl))))))
|
||||
|
||||
#?(:cljs
|
||||
(deftest cleanup-dirty-states
|
||||
|
|
@ -5,6 +5,8 @@
|
|||
:clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer [defstate]]])))
|
||||
|
||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||
|
||||
(defn f [n]
|
||||
(fn [m]
|
||||
(+ n m)))
|
||||
|
|
@ -3,6 +3,8 @@
|
|||
#?@(:cljs [[mount.core :as mount :refer-macros [defstate]]]
|
||||
:clj [[mount.core :as mount :refer [defstate]]])))
|
||||
|
||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||
|
||||
(defn dval
|
||||
"returns a value of DerefableState without deref'ing it"
|
||||
[d]
|
||||
|
|
@ -2,24 +2,26 @@
|
|||
(:require
|
||||
#?@(:cljs [[cljs.test :as t :refer-macros [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer-macros [defstate]]
|
||||
[app.websockets :refer [system-a]]
|
||||
[app.conf :refer [config]]
|
||||
[app.audit-log :refer [log]]]
|
||||
[tapp.websockets :refer [system-a]]
|
||||
[tapp.conf :refer [config]]
|
||||
[tapp.audit-log :refer [log]]]
|
||||
:clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer [defstate]]
|
||||
[app.nyse :refer [conn]]])
|
||||
[tapp.nyse :refer [conn]]])
|
||||
[mount.test.helper :refer [dval]]))
|
||||
|
||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||
|
||||
(defstate should-not-start :start (constantly 42))
|
||||
|
||||
#?(:clj
|
||||
(defn with-parts [f]
|
||||
(mount/start #'app.conf/config #'app.nyse/conn)
|
||||
(mount/start #'tapp.conf/config #'tapp.nyse/conn)
|
||||
(f)
|
||||
(mount/stop)))
|
||||
|
||||
(use-fixtures :once
|
||||
#?(:cljs {:before #(mount/start #'app.conf/config #'app.audit-log/log)
|
||||
#?(:cljs {:before #(mount/start #'tapp.conf/config #'tapp.audit-log/log)
|
||||
:after mount/stop}
|
||||
:clj with-parts))
|
||||
|
||||
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
[mount.test.fun-with-values :refer [private-f]]))
|
||||
|
||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||
|
||||
(use-fixtures :once
|
||||
#?(:cljs {:before #(mount/start #'mount.test.fun-with-values/private-f)
|
||||
:after mount/stop}
|
||||
|
|
@ -2,16 +2,18 @@
|
|||
(:require
|
||||
#?@(:cljs [[cljs.test :as t :refer-macros [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer-macros [defstate]]
|
||||
[app.websockets :refer [system-a]]
|
||||
[app.conf :refer [config]]
|
||||
[app.audit-log :refer [log]]]
|
||||
[tapp.websockets :refer [system-a]]
|
||||
[tapp.conf :refer [config]]
|
||||
[tapp.audit-log :refer [log]]]
|
||||
:clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer [defstate]]
|
||||
[app.conf :refer [config]]
|
||||
[app.nyse :refer [conn]]
|
||||
[app.example :refer [nrepl]]])
|
||||
[tapp.conf :refer [config]]
|
||||
[tapp.nyse :refer [conn]]
|
||||
[tapp.example :refer [nrepl]]])
|
||||
[mount.test.helper :refer [dval helper]]))
|
||||
|
||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||
|
||||
(defstate test-conn :start 42
|
||||
:stop (constantly 0))
|
||||
|
||||
|
|
@ -21,7 +23,7 @@
|
|||
(deftest start-with
|
||||
|
||||
(testing "should start with substitutes"
|
||||
(let [_ (mount/start-with {#'app.websockets/system-a #'mount.test.start-with/test-conn
|
||||
(let [_ (mount/start-with {#'tapp.websockets/system-a #'mount.test.start-with/test-conn
|
||||
#'mount.test.helper/helper #'mount.test.start-with/test-nrepl})]
|
||||
(is (map? (dval config)))
|
||||
(is (vector? (dval helper)))
|
||||
|
|
@ -30,7 +32,7 @@
|
|||
(mount/stop)))
|
||||
|
||||
(testing "should not start the substitute itself"
|
||||
(let [_ (mount/start-with {#'app.websockets/system-a #'mount.test.start-with/test-conn})]
|
||||
(let [_ (mount/start-with {#'tapp.websockets/system-a #'mount.test.start-with/test-conn})]
|
||||
(is (instance? mount.core.NotStartedState (dval test-conn)))
|
||||
(is (= 42 (dval system-a)))
|
||||
(mount/stop)))
|
||||
|
|
@ -60,15 +62,15 @@
|
|||
(deftest start-with
|
||||
|
||||
(testing "should start with substitutes"
|
||||
(let [_ (mount/start-with {#'app.nyse/conn #'mount.test.start-with/test-conn
|
||||
#'app.example/nrepl #'mount.test.start-with/test-nrepl})]
|
||||
(let [_ (mount/start-with {#'tapp.nyse/conn #'mount.test.start-with/test-conn
|
||||
#'tapp.example/nrepl #'mount.test.start-with/test-nrepl})]
|
||||
(is (map? (dval config)))
|
||||
(is (vector? (dval nrepl)))
|
||||
(is (= (dval conn) 42))
|
||||
(mount/stop)))
|
||||
|
||||
(testing "should not start the substitute itself"
|
||||
(let [_ (mount/start-with {#'app.nyse/conn #'mount.test.start-with/test-conn})]
|
||||
(let [_ (mount/start-with {#'tapp.nyse/conn #'mount.test.start-with/test-conn})]
|
||||
(is (instance? mount.core.NotStartedState (dval test-conn)))
|
||||
(is (= (dval conn) 42))
|
||||
(mount/stop)))
|
||||
|
|
@ -2,24 +2,26 @@
|
|||
(:require
|
||||
#?@(:cljs [[cljs.test :as t :refer-macros [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer-macros [defstate]]
|
||||
[app.websockets :refer [system-a]]
|
||||
[app.conf :refer [config]]
|
||||
[app.audit-log :refer [log]]]
|
||||
[tapp.websockets :refer [system-a]]
|
||||
[tapp.conf :refer [config]]
|
||||
[tapp.audit-log :refer [log]]]
|
||||
:clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer [defstate]]
|
||||
[app.conf :refer [config]]
|
||||
[app.nyse :refer [conn]]
|
||||
[app.example :refer [nrepl]]])
|
||||
[tapp.conf :refer [config]]
|
||||
[tapp.nyse :refer [conn]]
|
||||
[tapp.example :refer [nrepl]]])
|
||||
[mount.test.helper :refer [dval helper]]))
|
||||
|
||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||
|
||||
#?(:clj
|
||||
(defn without [f]
|
||||
(mount/start-without #'app.nyse/conn #'app.example/nrepl)
|
||||
(mount/start-without #'tapp.nyse/conn #'tapp.example/nrepl)
|
||||
(f)
|
||||
(mount/stop)))
|
||||
|
||||
(use-fixtures :once
|
||||
#?(:cljs {:before #(mount/start-without #'mount.test.helper/helper #'app.websockets/system-a)
|
||||
#?(:cljs {:before #(mount/start-without #'mount.test.helper/helper #'tapp.websockets/system-a)
|
||||
:after mount/stop}
|
||||
:clj without))
|
||||
|
||||
|
|
@ -2,22 +2,24 @@
|
|||
(:require
|
||||
#?@(:cljs [[cljs.test :as t :refer-macros [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer-macros [defstate]]
|
||||
[app.websockets :refer [system-a]]
|
||||
[app.conf :refer [config]]
|
||||
[app.audit-log :refer [log]]]
|
||||
[tapp.websockets :refer [system-a]]
|
||||
[tapp.conf :refer [config]]
|
||||
[tapp.audit-log :refer [log]]]
|
||||
:clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer [defstate]]
|
||||
[app.conf :refer [config]]
|
||||
[app.nyse :refer [conn]]
|
||||
[app.example :refer [nrepl]]])
|
||||
[tapp.conf :refer [config]]
|
||||
[tapp.nyse :refer [conn]]
|
||||
[tapp.example :refer [nrepl]]])
|
||||
[mount.test.helper :refer [dval helper]]))
|
||||
|
||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||
|
||||
#?(:cljs
|
||||
(deftest stop-except
|
||||
|
||||
(testing "should stop all except nrepl"
|
||||
(let [_ (mount/start)
|
||||
_ (mount/stop-except #'app.audit-log/log #'mount.test.helper/helper)]
|
||||
_ (mount/stop-except #'tapp.audit-log/log #'mount.test.helper/helper)]
|
||||
(is (= :started (dval helper)))
|
||||
(is (instance? datascript.db/DB @(dval log)))
|
||||
(is (instance? mount.core.NotStartedState (dval config)))
|
||||
|
|
@ -33,7 +35,7 @@
|
|||
|
||||
(testing "should stop all normally after stop-except"
|
||||
(let [_ (mount/start)
|
||||
_ (mount/stop-except #'app.audit-log/log #'mount.test.helper/helper)
|
||||
_ (mount/stop-except #'tapp.audit-log/log #'mount.test.helper/helper)
|
||||
_ (mount/stop)]
|
||||
(is (instance? mount.core.NotStartedState (dval config)))
|
||||
(is (instance? mount.core.NotStartedState (dval log)))
|
||||
|
|
@ -44,7 +46,7 @@
|
|||
|
||||
(testing "should stop all except nrepl"
|
||||
(let [_ (mount/start)
|
||||
_ (mount/stop-except #'app.nyse/conn #'app.conf/config)]
|
||||
_ (mount/stop-except #'tapp.nyse/conn #'tapp.conf/config)]
|
||||
(is (map? (dval config)))
|
||||
(is (instance? datomic.peer.LocalConnection (dval conn)))
|
||||
(is (instance? mount.core.NotStartedState (dval nrepl)))
|
||||
|
|
@ -59,7 +61,7 @@
|
|||
|
||||
(testing "should stop all normally after stop-except"
|
||||
(let [_ (mount/start)
|
||||
_ (mount/stop-except #'app.nyse/conn #'app.conf/config)
|
||||
_ (mount/stop-except #'tapp.nyse/conn #'tapp.conf/config)
|
||||
_ (mount/stop)]
|
||||
(is (instance? mount.core.NotStartedState (dval config)))
|
||||
(is (instance? mount.core.NotStartedState (dval conn)))
|
||||
|
|
@ -2,16 +2,18 @@
|
|||
(:require
|
||||
#?@(:cljs [[cljs.test :as t :refer-macros [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer-macros [defstate]]
|
||||
[app.websockets :refer [system-a]]
|
||||
[app.conf :refer [config]]
|
||||
[app.audit-log :refer [log]]]
|
||||
[tapp.websockets :refer [system-a]]
|
||||
[tapp.conf :refer [config]]
|
||||
[tapp.audit-log :refer [log]]]
|
||||
:clj [[clojure.test :as t :refer [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer [defstate]]
|
||||
[app.conf :refer [config]]
|
||||
[app.nyse :refer [conn]]
|
||||
[app.example :refer [nrepl]]])
|
||||
[tapp.conf :refer [config]]
|
||||
[tapp.nyse :refer [conn]]
|
||||
[tapp.example :refer [nrepl]]])
|
||||
[mount.test.helper :refer [dval]]))
|
||||
|
||||
#?(:clj (alter-meta! *ns* assoc ::load false))
|
||||
|
||||
(defn koncat [k s]
|
||||
(-> (name k)
|
||||
(str "-" (name s))
|
||||
|
|
@ -48,7 +50,7 @@
|
|||
|
||||
(testing "should resume _only suspendable_ states that are currently suspended"
|
||||
(let [_ (mount/start)
|
||||
_ (mount/stop #'app.websockets/system-a)
|
||||
_ (mount/stop #'tapp.websockets/system-a)
|
||||
_ (mount/suspend)
|
||||
_ (mount/resume)]
|
||||
(is (map? (dval config)))
|
||||
|
|
@ -82,7 +84,7 @@
|
|||
(testing "when replacing a non suspendable state with a suspendable one,
|
||||
the later should be able to suspend/resume,
|
||||
the original should not be suspendable after resume and preserve its lifecycle fns after rollback/stop"
|
||||
(let [_ (mount/start-with {#'app.websockets/system-a #'mount.test.suspend-resume/web-server})
|
||||
(let [_ (mount/start-with {#'tapp.websockets/system-a #'mount.test.suspend-resume/web-server})
|
||||
_ (mount/suspend)]
|
||||
(is (= (dval system-a) :w-suspended))
|
||||
(is (instance? mount.core.NotStartedState (dval web-server)))
|
||||
|
|
@ -107,7 +109,7 @@
|
|||
|
||||
(testing "should resume _only suspendable_ states that are currently suspended"
|
||||
(let [_ (mount/start)
|
||||
_ (mount/stop #'app.example/nrepl)
|
||||
_ (mount/stop #'tapp.example/nrepl)
|
||||
_ (mount/suspend)
|
||||
_ (mount/resume)]
|
||||
(is (map? (dval config)))
|
||||
|
|
@ -142,7 +144,7 @@
|
|||
(testing "when replacing a non suspendable state with a suspendable one,
|
||||
the later should be able to suspend/resume,
|
||||
the original should not be suspendable after resume and preserve its lifecycle fns after rollback/stop"
|
||||
(let [_ (mount/start-with {#'app.example/nrepl #'mount.test.suspend-resume/web-server})
|
||||
(let [_ (mount/start-with {#'tapp.example/nrepl #'mount.test.suspend-resume/web-server})
|
||||
_ (mount/suspend)]
|
||||
(is (= (dval nrepl) :w-suspended))
|
||||
(is (instance? mount.core.NotStartedState (dval web-server)))
|
||||
|
|
@ -176,7 +178,7 @@
|
|||
the original should still be suspended and preserve its lifecycle fns after the rollback/stop"
|
||||
(let [_ (mount/start)
|
||||
_ (mount/suspend)
|
||||
_ (mount/start-with {#'mount.test.suspend-resume/web-server #'app.nyse/conn}) ;; TODO: good to WARN on started states during "start-with"
|
||||
_ (mount/start-with {#'mount.test.suspend-resume/web-server #'tapp.nyse/conn}) ;; TODO: good to WARN on started states during "start-with"
|
||||
_ (mount/suspend)]
|
||||
(is (instance? datomic.peer.LocalConnection (dval conn)))
|
||||
(is (= (dval web-server) :w-suspended)) ;; since the "conn" does not have a resume method, so web-server was not started
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
(:require [clojure.test :as t :refer [is are deftest testing use-fixtures]]
|
||||
[mount.core :as mount :refer [defstate]]))
|
||||
|
||||
(alter-meta! *ns* assoc ::load false)
|
||||
|
||||
(defn f [n]
|
||||
(fn [m]
|
||||
(+ n m)))
|
||||
|
|
@ -3,6 +3,8 @@
|
|||
[mount.core :as mount :refer [defstate]]
|
||||
[mount.test.var.fun-with-values :refer [private-f]]))
|
||||
|
||||
(alter-meta! *ns* assoc ::load false)
|
||||
|
||||
(defn in-clj-mode [f]
|
||||
(mount/in-clj-mode)
|
||||
(require :reload 'mount.test.var.fun-with-values 'mount.test.var.private-fun)
|
||||
1
test/resources/mount.cljs.edn
Normal file
1
test/resources/mount.cljs.edn
Normal file
|
|
@ -0,0 +1 @@
|
|||
{:require [mount.test]}
|
||||
Loading…
Reference in a new issue