Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

template: service with donut and integrant options #22

Merged
merged 1 commit into from
Jul 14, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cljstyle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
;; cljstyle configuration
{:files
{:extensions #{"cljc" "cljs" "clj" "cljx" "edn"},
:ignore #{"checkouts" "dev" ".hg" "target" ".git" "mulog_publisher.clj"}},
:ignore #{"checkouts" "dev" ".hg" "target" ".git" "mulog_events.clj"}},
:rules
{:namespaces
{:enabled? false,
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/).

## [Unreleased]

## Added
- [#19](https://github.com/practicalli/project-templates/issues/19) `practicalli/minimal` template
- templates: link to Practicalli Clojure Project templates section for help after new project is created
- [#22](https://github.com/practicalli/project-templates/pull/22) Service template with `:component` option for `:donut` and `:integrant`

### Changed
- ci: update MegaLinter GitHub Action v7 in MegaLnter workflow
- ci: set monthly schedule and cron examples for alternative schedules
Expand Down
2 changes: 0 additions & 2 deletions resources/practicalli/service/build/deps.edn.template
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
;; org.slf4j/slf4j-nop {:mvn/version "1.7.32"}

;; System
aero/aero {:mvn/version "1.1.6"}
integrant/integrant {:mvn/version "0.8.0"}
org.clojure/clojure {:mvn/version "{{clojure-version}}"}}

:aliases
Expand Down
52 changes: 52 additions & 0 deletions resources/practicalli/service/build/deps_donut.edn.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{:paths
["src" "resources"]

:deps
{;; Service
http-kit/http-kit {:mvn/version "2.6.0"} ; latest "2.7.0-alpha1"
metosin/reitit {:mvn/version "0.5.13"}
metosin/reitit-dev {:mvn/version "0.5.18"} ; human readable exceptions

;; Logging
;; create events and send to publisher
com.brunobonacci/mulog {:mvn/version "0.9.0"}
;; JSON Console out support
com.brunobonacci/mulog-adv-console {:mvn/version "0.9.0"}
;; Optional: suppress slf4j warning
;; org.slf4j/slf4j-nop {:mvn/version "1.7.32"}

;; System
aero/aero {:mvn/version "1.1.6"}
party.donut/system {:mvn/version "0.0.202"}
org.clojure/clojure {:mvn/version "{{clojure-version}}"}}

:aliases
{;; Clojure.main execution of application
:run/service
{:main-opts ["-m" "{{top/ns}}.{{main/ns}}.service"]}

;; Clojure.exec execution of specified function
:run/greet
{:exec-fn {{top/ns}}.{{main/ns}}.service/greet
:exec-args {:name "Clojure"}}

;; Add libraries and paths to support additional test tools
:test/env
{}

;; Test runner - local and CI
;; call with :watch? true to start file watcher and re-run tests on saved changes
:test/run
{:extra-paths ["test"]
:extra-deps {lambdaisland/kaocha {:mvn/version "1.85.1342"}}
:main-opts ["-m" "kaocha.runner"]
:exec-fn kaocha.runner/exec-fn
:exec-args {:randomize? false
:fail-fast? true}}

;; tools.build `build.clj` built script
:build
{:replace-paths ["."]
:replace-deps {io.github.clojure/tools.build
{:git/tag "v0.9.4" :git/sha "76b78fe"}}
:ns-default build}}}
52 changes: 52 additions & 0 deletions resources/practicalli/service/build/deps_integrant.edn.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{:paths
["src" "resources"]

:deps
{;; Service
http-kit/http-kit {:mvn/version "2.6.0"} ; latest "2.7.0-alpha1"
metosin/reitit {:mvn/version "0.5.13"}
metosin/reitit-dev {:mvn/version "0.5.18"} ; human readable exceptions

;; Logging
;; create events and send to publisher
com.brunobonacci/mulog {:mvn/version "0.9.0"}
;; JSON Console out support
com.brunobonacci/mulog-adv-console {:mvn/version "0.9.0"}
;; Optional: suppress slf4j warning
;; org.slf4j/slf4j-nop {:mvn/version "1.7.32"}

;; System
aero/aero {:mvn/version "1.1.6"}
integrant/integrant {:mvn/version "0.8.0"}
org.clojure/clojure {:mvn/version "{{clojure-version}}"}}

:aliases
{;; Clojure.main execution of application
:run/service
{:main-opts ["-m" "{{top/ns}}.{{main/ns}}.service"]}

;; Clojure.exec execution of specified function
:run/greet
{:exec-fn {{top/ns}}.{{main/ns}}.service/greet
:exec-args {:name "Clojure"}}

;; Add libraries and paths to support additional test tools
:test/env
{}

;; Test runner - local and CI
;; call with :watch? true to start file watcher and re-run tests on saved changes
:test/run
{:extra-paths ["test"]
:extra-deps {lambdaisland/kaocha {:mvn/version "1.85.1342"}}
:main-opts ["-m" "kaocha.runner"]
:exec-fn kaocha.runner/exec-fn
:exec-args {:randomize? false
:fail-fast? true}}

;; tools.build `build.clj` built script
:build
{:replace-paths ["."]
:replace-deps {io.github.clojure/tools.build
{:git/tag "v0.9.4" :git/sha "76b78fe"}}
:ns-default build}}}
55 changes: 55 additions & 0 deletions resources/practicalli/service/dev/mulog_events.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
;; ---------------------------------------------------------
;; Mulog Global Context and Custom Publisher
;;
;; - set event log global context
;; - tap publisher for use with Portal and other tap sources
;; - publish all mulog events to Portal tap source
;; ---------------------------------------------------------

(ns mulog-events
(:require
[com.brunobonacci.mulog :as mulog]
[com.brunobonacci.mulog.buffer :as mulog-buffer]))

;; ---------------------------------------------------------
;; Set event global context
;; - information added to every event for REPL workflow
(mulog/set-global-context! {:app-name "{{main/ns}} Service",
:version "0.1.0", :env "dev"})
;; ---------------------------------------------------------

;; ---------------------------------------------------------
;; Mulog event publishing

(deftype TapPublisher
[buffer transform]
com.brunobonacci.mulog.publisher.PPublisher
(agent-buffer [_] buffer)
(publish-delay [_] 200)
(publish [_ buffer]
(doseq [item (transform (map second (mulog-buffer/items buffer)))]
(tap> item))
(mulog-buffer/clear buffer)))

#_{:clj-kondo/ignore [:unused-private-var]}
(defn ^:private tap-events
[{:keys [transform] :as _config}]
(TapPublisher. (mulog-buffer/agent-buffer 10000) (or transform identity)))

(def tap-publisher
"Start mulog custom tap publisher to send all events to Portal
and other tap sources
`mulog-tap-publisher` to stop publisher"
(mulog/start-publisher!
{:type :custom, :fqn-function "mulog-events/tap-events"}))

#_{:clj-kondo/ignore [:unused-public-var]}
(defn stop
"Stop mulog tap publisher to ensure multiple publishers are not started
Recommended before using `(restart)` or evaluating the `user` namespace"
[]
tap-publisher)

;; Example mulog event message
;; (mulog/log ::dev-user-ns :message "Example event message" :ns (ns-publics *ns*))
;; ---------------------------------------------------------
26 changes: 0 additions & 26 deletions resources/practicalli/service/dev/mulog_publisher.clj

This file was deleted.

24 changes: 24 additions & 0 deletions resources/practicalli/service/dev/portal.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
(ns portal
(:require
;; Data inspector
[portal.api :as inspect]))


;; ---------------------------------------------------------
;; Start Portal and capture all evaluation results

;; Open Portal window in browser with dark theme
;; https://cljdoc.org/d/djblue/portal/0.37.1/doc/ui-concepts/themes
;; Portal options:
;; - light theme {:portal.colors/theme :portal.colors/solarized-light}
;; - dark theme {:portal.colors/theme :portal.colors/gruvbox}

(def instance
"Open portal window if no portal sessions have been created.
A portal session is created when opening a portal window"
(or (seq (inspect/sessions))
(inspect/open {:portal.colors/theme :portal.colors/gruvbox})))

;; Add portal as tapsource (add to clojure.core/tapset)
(add-tap #'portal.api/submit)
;; ---------------------------------------------------------
51 changes: 51 additions & 0 deletions resources/practicalli/service/dev/system_repl.clj.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
;; ---------------------------------------------------------
;; System REPL - Atom Restart
;;
;; Tools for REPl workflow with Aton reference to HTTP server
;; https://practical.li/clojure-web-services/app-servers/simple-restart/
;; ---------------------------------------------------------

(ns system-repl
(:require
[org.httpkit.server :as http-server]
[clojure.tools.namespace.repl :refer [refresh]]
[{{top/ns}}.{{main/ns}}.service :as service]))

;; ---------------------------------------------------------
;; HTTP Server State

(defonce http-server-instance (atom nil))
;; ---------------------------------------------------------


;; ---------------------------------------------------------
;; REPL workflow commands

(defn stop
"Gracefully shutdown the server, waiting 100ms"
[]
(when-not (nil? @http-server-instance)
(@http-server-instance :timeout 100)
(reset! http-server-instance nil)
(println "INFO: HTTP server shutting down...")))

(defn start
"Start the application server and run the application"
[port]
(let [port (Integer/parseInt
(or port
(System/getenv "PORT")
"8080"))])
(println "INFO: Starting server on port: " port)

(reset! http-server-instance
(service/http-service-start (Integer/parseInt port))))

(defn restart
"Stop the http server, refresh changed namespacea and start the http server again"
[]
(stop)
(refresh) ;; Refresh changed namespaces
(start))
;; ---------------------------------------------------------

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
;; ---------------------------------------------------------
;; Donut System REPL
;;
;; Tools for REPl workflow with Donut system components
;; ---------------------------------------------------------

(ns system-repl
"Tools for REPl workflow with Donut system components"
(:require
[donut.system :as donut]
[donut.system.repl :as donut-repl]
[donut.system.repl.state :as donut-repl-state]
[{{top/ns}}.{{main/ns}}.system :as system]))


(defmethod donut/named-system :donut.system/repl
[_] system/main)

(defn start
"Start system with donut, optionally passing a named system"
([] (donut-repl/start))
([system-config] (donut-repl/start system-config)))

(defn stop
"Stop the currently running system"
[] (donut-repl/stop))

(defn restart
"Restart the system with donut repl,
Uses clojure.tools.namespace.repl to reload namespaces
`(clojure.tools.namespace.repl/refresh :after 'donut.system.repl/start)`"
[] (donut-repl/restart))

(defn system
"Return: fully qualified hash-map of system state"
[] donut-repl-state/system)
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
;; ---------------------------------------------------


(ns system
(ns system-repl
"Configure the system components and provide Integrant REPL convenience functions
to start/stop/restart components and show system configuration"
(:require
Expand Down