A Clojure map which implements java.io.Closeable.
;; in your project
(defn start
"Return an running context with stateful references which can be closed."
[config]
(assoc config
:server (http/start-server (api context) {:port 3030})
:producer (kafka-producer config)
:consumer (kafka-consumer config)))
;; in test file
(with-open [context (piotr-yuxuan/closeable-map (start config))]
(testing "unit test with isolated, repeatable context"
(is (= :yay/🚀 (some-business/function context)))))
You might not need closeable-map, perhaps
jarohen/with-open or
robertluo/fun-map are better fit
for you. They provide more general, more powerful tools. This library
focus on doing one thing: a map which represents a execution context,
which you can close.
Some Clojure datastructures implement IFn:
({:a 1} :a) ;; => 1
(remove #{:a} [:a :b :c]) ;; => '(:b :c)
([:a :b :c] 1) ;; => :b
Clojure maps (IPersistentMap) implement IFn, for invoke() of one
argument (a key) with an optional second argument (a default value),
i.e. maps are functions of their keys. nil keys and values are fine.
I have found desirable in some cases to put stateful references in a
context map:
;; Start an API
(defn -main
[]
(let [config (config/load-config)
context {:producer (kafka-producer config)
:consumer (kafka-consumer config)}]
(http/start-server
(api context)
{:port 3030})))
So far so good, but what about testing? It would be nice to have tests like:
;; doesn't work
(with-open [context {:producer (kafka-producer config)
:consumer (kafka-consumer config)}]
(is (= :yay/🚀 (some-business/function context))))
so that a test context is declared, assumptions are checked against it, and finally context is closed.
This library defines a new type of map, CloseableMap, which implements
java.io.Closeable. It provides one function to create such map from a
Clojure map. When key :close is present, it is assumed that it is a
function which knows how to destroy the state, or a collection of
functions, of which each destroys of part of the state.
(with-open [context (closeable-map {:producer (kafka-producer config)
:consumer (kafka-consumer config)
:close [(fn [{:keys [producer]}] (.close producer))
(fn [{:keys [consumer]}] (.close consumer))]})]
(is (= :yay/🚀 (some-business/function context))))
deps.edn guide: https://clojure.org/guides/deps_and_clideps.edn reference: https://clojure.org/reference/deps_and_cliInvoking the function provided by this library from the command-line. It returns an unimpressive map, which is what we expect:
clojure -X:run-x :arg '{:a 1}'
{:a 1}
Also, see ./test/piotr~yuxuan~/closeable~maptest~.clj.
This project was created with:
clojure -X:project/new :name piotr-yuxuan/closeable-map
Run the project's tests:
clojure -M:test:runner
Lint your code with:
clojure -M:lint/idiom
clojure -M:lint/kondo
Visualise links between project vars with:
mkdir graphs
clojure -M:graph/vars-svg
Build a deployable jar of this library:
lein pom
clojure -X:jar
This will update the generated pom.xml file to keep the dependencies
synchronized with your deps.edn file.
Install it locally:
lein pom
clojure -X:install
Create a new version once a jar has been created:
lein pomVersion x.y.zDeploy it to Clojars -- needs CLOJARS_USERNAME and CLOJARS_PASSWORD
environment variables (requires the pom.xml file):
lein pom
clojure -X:deploy
Deploy it to GitHub packages with this guide and:
mvn deploy -DaltDeploymentRepository=github::default::https://maven.pkg.github.com/piotr-yuxuan/closeable-map
pom.xmlIf you don't plan to install/deploy the library, you can remove the
pom.xml file but you will also need to remove :sync-pom true from
the deps.edn file (in the :exec-args for depstar).
As of now it is suggested to run lein pom to update the pom before
installing a jar or deploying a new version, so that the file pom.xml
is correctly updated by Leiningen (especially the scm revision), which I
don't know yet how to do with deps.edn tooling.
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |