Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions examples/integrant-system/bases/system/deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{:paths ["src" "resources"]
:deps {com.zaxxer/HikariCP {:mvn/version "5.1.0"}
integrant/integrant {:mvn/version "0.10.0"}
org.clojure/tools.logging {:mvn/version "1.2.4"}
org.clojure/tools.namespace {:mvn/version "1.3.0"}}
:aliases {:test {:extra-paths ["test"]
:extra-deps {}}}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
(ns
^{:author "Mark Sto"}
integrant.system.config
(:require [clojure.tools.logging :as log]
[integrant.config.interface :as config]
[integrant.core :as ig]))

(defmethod ig/init-key :integrant.system/config
[_ _]
(log/info "Loading configuration")
(config/load-config))
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
(ns
^{:author "Mark Sto"}
integrant.system.core
(:require [clojure.pprint :as pp]
[clojure.tools.logging :as log]
[integrant.core :as ig]
[integrant.system.state :as state]))

;; Integrant System

(def default-ig-config
{:integrant.system/config {}
:integrant.system/embedded-pg {:config (ig/ref :integrant.system/config)
#_#_:log-file "path/to/pg-logs-redirection"}
:integrant.system/data-source {:config (ig/ref :integrant.system/config)
:postgres (ig/ref :integrant.system/embedded-pg)}})

(defn halt-system! []
(state/stop!)
::stopped)

(defn init-system!
([]
(init-system! default-ig-config))
([ig-config]
(log/info "Starting system with config:\n"
(with-out-str (pp/pprint ig-config)))
(try
(halt-system!)
(state/start! ig-config)
::started
(catch Exception ex
(log/error ex "Failed to start the system")
(halt-system!)
::failed-to-start))))

;; Base API

(defn shutdown!
[]
(let [halt-res (halt-system!)]
(shutdown-agents)
halt-res))

(defn launch!
[]
(.addShutdownHook (Runtime/getRuntime) (Thread. shutdown!))
(init-system!))

(defn -main
[& _]
(launch!))
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
(ns
^{:author "Mark Sto"}
integrant.system.data_source
(:require [clojure.tools.logging :as log]
[integrant.core :as ig]
[integrant.pg-ops.interface :as pg-ops])
(:import (com.zaxxer.hikari HikariDataSource)))

(defn -conn-pool
^HikariDataSource
[{:keys [classname
subprotocol
subname
user
password]
:as db-spec}]
(log/info "DB Spec:" db-spec)
(let [conn-pool (doto (HikariDataSource.)
(.setDriverClassName classname)
(.setJdbcUrl (str "jdbc:" subprotocol ":" subname))
(.setUsername user)
(.setPassword password))]
;; NB: Initializing the pool and performing a validation check.
(.close (.getConnection conn-pool))
conn-pool))

(defmethod ig/init-key :integrant.system/data-source
[_ {:keys [config]}]
(log/info "Initializing JDBC DataSource")
(let [db-spec (-> (:db+creds config)
(assoc :port (get-in config [:postgres :port]))
(pg-ops/->db-spec))]
(-conn-pool db-spec)))

(defmethod ig/halt-key! :integrant.system/data-source
[_ ^HikariDataSource data-source]
(log/info "Closing JDBC DataSource")
(when data-source
(.close data-source)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
(ns
^{:author "Mark Sto"}
integrant.system.embedded-pg
(:require [clojure.tools.logging :as log]
[integrant.core :as ig]
[integrant.embedded-pg.interface :as embedded-pg]))

(defmethod ig/init-key :integrant.system/embedded-pg
[_ {:keys [config log-file]}]
(let [pg-config {:port (get-in config [:postgres :port])
:log-file log-file}]
(log/info "Initializing Postgres with config:" pg-config)
(embedded-pg/start-postgres! pg-config)))

(defmethod ig/halt-key! :integrant.system/embedded-pg
[_ embedded-pg]
(when embedded-pg
(log/info "Halting Postgres")
(embedded-pg/stop-postgres! embedded-pg)
nil))
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
(ns
^{:author "Mark Sto"}
integrant.system.state
(:require [clojure.tools.logging :as log]
[clojure.tools.namespace.repl :as repl]
[integrant.core :as ig]))

(repl/disable-reload!)

(def *state
"Stores the current Integrant system and its config."
(atom nil))

(defn start!
[ig-config]
(when ig-config
(log/info "Starting Integrant system")
(ig/load-namespaces ig-config)
(reset! *state {:system (ig/init ig-config)
:config ig-config})))

(defn stop!
[]
(log/info "Stopping Integrant system")
(-> (swap-vals! *state
(fn [{:keys [system]}]
(when system
(ig/halt! system))
nil))
(first)
:config))

(defn restart!
[]
(let [ig-config (stop!)]
(start! ig-config)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
(ns
^{:author "Mark Sto"}
integrant.system.core-test
(:require [clojure.string :as str]
[clojure.test :refer :all]
[integrant.pg-ops.interface :as pg-ops]
[integrant.system.core :as system]
[integrant.system.state :as state]))

(defn- get-pg-version
[]
(-> @state/*state
(get-in [:system :integrant.system/data-source])
(pg-ops/query-version)))

(deftest integrant-system-lifecycle
(testing "System launch succeeds"
(is (= ::system/started (system/launch!)))
(let [system-state @state/*state]
(is (map? system-state))
(is (contains? system-state :system))
(is (contains? system-state :config))))

(testing "All system components are initialized and functional"
(is (str/starts-with? (get-pg-version) "PostgreSQL")))

(testing "System restart succeeds and config does not change"
(let [old-config (get @state/*state :config)
new-state (state/restart!)]
(is (map? new-state))
(is (contains? new-state :system))
(is (contains? new-state :config))
(is (= old-config (:config new-state)))))

(testing "System shutdown succeeds"
(is (= ::system/stopped (system/shutdown!)))
(let [system-state @state/*state]
(is (nil? system-state))
(is (thrown? Exception (get-pg-version))))))

(comment
(run-tests)
.)
4 changes: 4 additions & 0 deletions examples/integrant-system/components/config/deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{:paths ["src" "resources"]
:deps {}
:aliases {:test {:extra-paths ["test"]
:extra-deps {}}}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
(ns
^{:author "Mark Sto"}
integrant.config.core)

;; NB: This should normally use some library to load a system configuration map.
;; However, we keep things simple for demonstration purposes.
(defn load-config []
{:postgres {:port 54321}
:db+creds {:dbname "postgres"
:user "postgres"
:password "postgres"}})
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(ns
^{:doc "An abstract system configuration as a Polylith component"
:author "Mark Sto"}
integrant.config.interface
(:require [integrant.config.core :as core]))

(defn load-config
[]
(core/load-config))
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(ns integrant.config.interface-test
(:require [clojure.test :as test :refer :all]
[integrant.config.interface :as config]))

(deftest dummy-test
(is (= 1 1)))
4 changes: 4 additions & 0 deletions examples/integrant-system/components/embedded-pg/deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{:paths ["src"]
:deps {io.zonky.test/embedded-postgres {:mvn/version "2.0.7"}}
:aliases {:test {:extra-paths ["test"]
:extra-deps {}}}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
(ns
^{:author "Mark Sto"}
integrant.embedded-pg.core
(:require [clojure.java.io :as io])
(:import
(io.zonky.test.db.postgres.embedded EmbeddedPostgres EmbeddedPostgres$Builder)
(java.lang ProcessBuilder$Redirect)))

(defn ->embedded-pg-builder
^EmbeddedPostgres$Builder
[{:keys [port log-file] :as _pg-config}]
{:pre [(some? port)]}
(let [pg-builder (-> (EmbeddedPostgres/builder)
(.setPort port))]
(when log-file
(let [log-redirector (ProcessBuilder$Redirect/appendTo (io/file log-file))]
(-> pg-builder
(.setOutputRedirector log-redirector)
(.setErrorRedirector log-redirector))))
pg-builder))

(defn start-postgres!
[pg-config]
(.start (->embedded-pg-builder pg-config)))

(defn stop-postgres!
[^EmbeddedPostgres embedded-pg]
(when embedded-pg
(.close embedded-pg)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
(ns
^{:doc "An embedded PostgreSQL DBMS as a Polylith component"
:author "Mark Sto"}
integrant.embedded-pg.interface
(:require [integrant.embedded-pg.core :as core])
(:import
(io.zonky.test.db.postgres.embedded EmbeddedPostgres)))

(defn start-postgres!
[pg-config]
(core/start-postgres! pg-config))

(defn stop-postgres!
[^EmbeddedPostgres embedded-pg]
(core/stop-postgres! embedded-pg))
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(ns integrant.embedded-pg.interface-test
(:require [clojure.test :as test :refer :all]
[integrant.embedded-pg.interface :as postgres]))

(deftest dummy-test
(is (= 1 1)))
4 changes: 4 additions & 0 deletions examples/integrant-system/components/pg-ops/deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{:paths ["src"]
:deps {org.clojure/java.jdbc {:mvn/version "0.7.12"}}
:aliases {:test {:extra-paths ["test"]
:extra-deps {}}}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
(ns
^{:author "Mark Sto"}
integrant.pg-ops.core
(:require [clojure.java.jdbc :as jdbc]))

(defn ->db-spec
[{:keys [port dbname user password] :as _db+creds}]
{:classname "org.postgresql.Driver"
:subprotocol "postgresql"
:subname (format "//localhost:%s/%s" port dbname)
:user (or user "postgres")
:password (or password "postgres")})

(defn query-version
[data-source]
(jdbc/with-db-connection
[conn {:datasource data-source}]
(some-> (jdbc/query conn ["SELECT version()"])
(first)
:version)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
(ns
^{:doc "A set of PostgreSQL-specific operations as a Polylith component"
:author "Mark Sto"}
integrant.pg-ops.interface
(:require [integrant.pg-ops.core :as core]))

(defn ->db-spec
[db+creds]
(core/->db-spec db+creds))

(defn query-version
[data-source]
(core/query-version data-source))
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(ns integrant.pg-ops.interface-test
(:require [clojure.test :as test :refer :all]
[integrant.pg-ops.interface :as pg-ops]))

(deftest dummy-test
(is (= 1 1)))
21 changes: 21 additions & 0 deletions examples/integrant-system/deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{:aliases {:dev {:extra-paths ["development/src"
"development/resources"]

:extra-deps {poly+integrant/system {:local/root "bases/system"}
poly+integrant/config {:local/root "components/config"}
poly+integrant/embedded-pg {:local/root "components/embedded-pg"}
poly+integrant/pg-ops {:local/root "components/pg-ops"}

integrant/repl {:mvn/version "0.3.3"}

org.clojure/clojure {:mvn/version "1.11.1"}
org.clojure/tools.logging {:mvn/version "1.2.4"}

org.apache.logging.log4j/log4j-api {:mvn/version "2.23.1"}
org.apache.logging.log4j/log4j-core {:mvn/version "2.23.1"}
org.apache.logging.log4j/log4j-slf4j-impl {:mvn/version "2.23.1"}}}

:test {:extra-paths ["bases/system/test"]}

:poly {:main-opts ["-m" "polylith.clj.core.poly-cli.core"]
:extra-deps {polylith/clj-poly {:mvn/version "0.2.18"}}}}}
14 changes: 14 additions & 0 deletions examples/integrant-system/development/resources/log4j2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.nnn} %-5p %c{1}:%L - %m%n"/>
</Console>
</Appenders>

<Loggers>
<Root level="info" includeLocation="true">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
Loading