Last active
August 4, 2019 18:12
-
-
Save aamedina/937349a35e724753d00dc47d7c27d7e3 to your computer and use it in GitHub Desktop.
a simple pattern for data-driven reloadable systems with Clojure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;;; deps.edn | |
| {:deps | |
| {org.clojure/clojure {:mvn/version "1.10.0-beta7"} | |
| ;; this version is required for clojure.tools.deps.alpha.repl/add-lib | |
| org.clojure/tools.deps.alpha {:git/url "https://github.com/clojure/tools.deps.alpha.git" | |
| :sha "f6c080bd0049211021ea59e516d1785b08302515"} | |
| org.clojure/tools.namespace {:mvn/version "0.2.11"} | |
| com.walmartlabs/schematic {:mvn/version "1.1.0"} | |
| reloaded.repl {:mvn/version "0.2.4"} | |
| ;; example libs we might componentize | |
| com.datomic/datomic-free {:mvn/version "0.9.5697"} | |
| org.neo4j/neo4j {:mvn/version "3.4.10"}} | |
| :paths ["src"]} | |
| ;;; defsys.edn | |
| {:neo4j {:sc/create-fn defsys-example.system.neo4j/map->Neo4j} | |
| :datomic {:sc/create-fn defsys-example.system.datomic/map->Datomic | |
| :uri "datomic:mem://defsys-example"} | |
| :app {:sc/create-fn defsys-example.system.app/map->App | |
| :sc/refs [:neo4j :datomic]}} | |
| ;;; defsys.edn ends here | |
| ;;; src/defsys_example/system.clj | |
| (ns defsys-example.system | |
| "A dynamically reloadable data-oriented system definition for the game. | |
| This tiny library ties the following Clojure libraries together for | |
| managing systems of stateful components: | |
| https://github.com/clojure/tools.deps.alpha/tree/add-lib | |
| Downloads and loads libraries from any Java artifact compatible with | |
| tools.deps (Maven, Git repos, local projects, etc.) This is used for | |
| adding new dependencies to the project during development without | |
| restarting the game. | |
| https://github.com/stuartsierra/component | |
| 'Component' is a tiny Clojure framework for managing the lifecycle | |
| and dependencies of software components which have runtime state. | |
| https://github.com/walmartlabs/schematic | |
| Schematic is a Clojure library which aids in assembling Component | |
| systems from configuration data. | |
| Only one function is public: `make-system`, which can be given to | |
| repl.reloaded/set-init! to enable REPL-based interactive code | |
| reloading upon reset in your project's user.clj." | |
| (:require | |
| [clojure.tools.deps.alpha.repl :as deps-repl] | |
| [com.walmartlabs.schematic :as scm])) | |
| (defn- load-deps | |
| "Loads the project's deps.edn from disk. | |
| Downloads and installs into the current classloader each library | |
| specified as :deps in the parsed Clojure data." | |
| ([] | |
| (load-deps (str (System/getProperty "user.dir") "/deps.edn"))) | |
| ([deps-path] | |
| (doseq [[lib coord] (:deps (read-string (slurp deps-path)))] | |
| (deps-repl/add-lib lib coord)))) | |
| (defn- load-defsys | |
| "Loads the project's defsys.edn from disk. | |
| First it synchronizes the runtime dependencies with the project's | |
| deps.edn, and then reads the system definition from disk." | |
| ([] | |
| (load-defsys (str (System/getProperty "user.dir") "/defsys.edn"))) | |
| ([defsys-path] | |
| (load-deps) | |
| (read-string (slurp defsys-path)))) | |
| (defn make-system | |
| "Assembles and returns a system-map from disk and additional | |
| (optional) config. | |
| This system is compatible with Stuart Sierra's Component library and | |
| can be started and stopped at runtime." | |
| ([] | |
| (make-system nil)) | |
| ([config] | |
| (scm/assemble-system (merge (load-defsys) config)))) | |
| ;;; src/defsys_example/system.clj ends here | |
| ;;; src/user.clj | |
| (ns user | |
| (:require | |
| ;; Clojure libs | |
| [clojure.repl :refer [doc source pst]] | |
| [clojure.java.io :as io] | |
| [clojure.string :as str] | |
| [clojure.pprint :refer [pp pprint]] | |
| ;; System namespaces | |
| [defsys-example.system :as sys] | |
| ;; Code reloading support | |
| [clojure.tools.namespace.repl :refer [set-refresh-dirs]] | |
| [reloaded.repl :refer [system init start stop go reset reset-all]])) | |
| (set-refresh-dirs "src") | |
| ;; Dev defsys overrides | |
| (def dev-config | |
| {}) | |
| (reloaded.repl/set-init! #(sys/make-system dev-config)) | |
| ;;; src/user.clj ends here |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment