closeable-map
This small library defines a new type of Clojure that you can close. It is a tiny alternative to more capable projects:
with-open
:
jarohen/with-open;; In your project, require:
(require '[piotr-yuxuan.closeable-map :as closeable-map])
(defn start
"Return a running context with values that can be closed."
[config]
(closeable-map/closeable-map
{;; Kafka producers/consumers are `java.io.Closeable`.
:producer (kafka-producer config)
:consumer (kafka-consumer config)
;; File streams are `java.io.Closeable` too:
:outfile (io/output-stream (io/file "/tmp/outfile.txt"))
;; Closeable maps can be nested.
:db {:db-conn (jdbc/get-connection (:db config))}
;; Some libs return a function which when called stop the server, like:
:server ^::closeable-map/fn (http/start-server (api config) (:server config))}))
;; Then you can start/stop the app in the repl with:
(comment
(def config (load-config))
(def system (start config))
;; Stop/close all processes/resources with:
(.close system)
)
;; You can use it in conjunction with `with-open` like in test file:
(with-open [system (start config)]
(testing "unit test with isolated, repeatable context"
(is (= :yay/🚀 (some-business/function context)))))
When (.close system)
is executed, it will:
java.io.Closeable
and java.lang.AutoCloseable
;^::closeable-map/fn
;Closeable
tagged with ^::closeable-map/ignore
;::closeable-map/before-close
or ::closeable-map/before-close
are present, they will be assumed
as a function which takes one argument (the map itself) and used
run additional closing logic:
(closeable-map
{;; This function will be executed before the auto close.
::closeable-map/before-close (fn [this-map] (flush!))
;; Kafka producers/consumers are java.io.Closeable
:producer (kafka-producer config)
:consumer (kafka-consumer config)
;; This function will be executed after the auto close.
::closeable-map/after-close (fn [this-map] (garbage/collect!))
}
)
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.
This library defines a new data strucure, CloseableMap. It is exposed
as an instance of java.io.Closeable
which is a subinterface of
java.lang.AutoCloseable
. When trying to close its values, it looks
for instances of the latter. As such, it tries to be most general.
(require '[clojure.data])
(clojure.data/diff
(ancestors (class {}))
(ancestors CloseableMap))
;; =>
[;; Ancestors of Clojure map only but not CloseableMap.
#{clojure.lang.AFn ; Concrete type, but see below for IFn.
clojure.lang.APersistentMap
clojure.lang.IEditableCollection
clojure.lang.IKVReduce
clojure.lang.IMapIterable
java.io.Serializable}
;; Ancestors of CloseableMap only.
#{clojure.lang.IType
java.io.Closeable
java.lang.AutoCloseable
java.util.Iterator
potemkin.collections.PotemkinMap
potemkin.types.PotemkinType}
;; Ancestors common to both types.
#{clojure.lang.Associative
clojure.lang.Counted
clojure.lang.IFn
clojure.lang.IHashEq
clojure.lang.ILookup
clojure.lang.IMeta
clojure.lang.IObj
clojure.lang.IPersistentCollection
clojure.lang.IPersistentMap
clojure.lang.MapEquivalence
clojure.lang.Seqable
java.lang.Iterable
java.lang.Object
java.lang.Runnable
java.util.Map
java.util.concurrent.Callable}]
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close