[nop] Move *middleware* and *ctx* to Encore sigs API

This commit is contained in:
Peter Taoussanis 2024-08-05 11:44:30 +02:00
parent 2d4b049717
commit d2b3e7201d
3 changed files with 22 additions and 113 deletions

View file

@ -18,15 +18,13 @@
#?(:cljs
(:require-macros
[taoensso.telemere :refer
[set-ctx! with-ctx with-ctx+
set-middleware! with-middleware
with-signal with-signals
[with-signal with-signals
signal! event! log! trace! spy! catch->error!
;; Via `sigs/def-api`
without-filters with-kind-filter with-ns-filter with-id-filter
with-min-level with-handler with-handler+]])))
with-min-level with-handler with-handler+
with-ctx with-ctx+ with-middleware]])))
(comment
(remove-ns 'taoensso.telemere)
@ -83,82 +81,6 @@
(impl/defhelp help:signal-content :signal-content)
(impl/defhelp help:environmental-config :environmental-config))
;;;; Context
(enc/defonce default-ctx
"Default root (base) value of `*ctx*` var.
Defaults to `nil`, controlled by:
(get-env {:as :edn} :taoensso.telemere/default-ctx<.platform><.edn>)
See `get-env` for details."
(enc/get-env {:as :edn} :taoensso.telemere/default-ctx<.platform><.edn>))
(enc/def* ^:dynamic *ctx*
"Dynamic context: arbitrary user-level state attached as `:ctx` to all signals.
Value may be any type, but is usually nil or a map.
Re/bind dynamic value using `with-ctx`, `with-ctx+`, or `binding`.
Modify root (base) value using `set-ctx!`.
Default root (base) value is `default-ctx`.
Note that as with all dynamic Clojure vars, \"binding conveyance\" applies
when using futures, agents, etc.
Tips:
- Value may be (or may contain) an atom if you want mutable semantics
- Value may be of form {<scope-id> <data>} for custom scoping, etc."
default-ctx)
#?(:clj
(defmacro set-ctx!
"Set `*ctx*` var's root (base) value. See `*ctx*` for details."
[root-ctx-val] `(enc/set-var-root! *ctx* ~root-ctx-val)))
#?(:clj
(defmacro with-ctx
"Evaluates given form with given `*ctx*` value. See `*ctx*` for details."
[ctx-val form] `(binding [*ctx* ~ctx-val] ~form)))
(comment (with-ctx "my-ctx" *ctx*))
#?(:clj
(defmacro with-ctx+
"Evaluates given form with updated `*ctx*` value.
`update-map-or-fn` may be:
- A map to merge with current `*ctx*` value, or
- A unary fn to apply to current `*ctx*` value
See `*ctx*` for details."
[update-map-or-fn form]
`(binding [*ctx* (impl/update-ctx *ctx* ~update-map-or-fn)]
~form)))
(comment (with-ctx {:a :A1 :b :B1} (with-ctx+ {:a :A2} *ctx*)))
;;;; Signal middleware
(enc/defonce ^:dynamic *middleware*
"Optional (fn [signal]) => ?modified-signal to apply (once) when
signal is created. When middleware returns nil, skips all handlers.
Compose multiple middleware fns together with `comp-middleware`.
Re/bind dynamic value using `with-middleware`, `binding`.
Modify root (base) value using `set-middleware!`."
nil)
#?(:clj
(defmacro set-middleware!
"Set `*middleware*` var's root (base) value. See `*middleware*` for details."
[?root-middleware-fn] `(enc/set-var-root! *middleware* ~?root-middleware-fn)))
#?(:clj
(defmacro with-middleware
"Evaluates given form with given `*middleware*` value.
See `*middleware*` for details."
[?middleware-fn form] `(binding [*middleware* ~?middleware-fn] ~form)))
;;;; Signal creators
;; - signal! [ opts] ; => allowed? / run result (value or throw)
;; - event! [id ] [id level-or-opts] ; id + ?level => allowed? ; Sole signal with descending main arg!

View file

@ -62,22 +62,6 @@
(comment (enc/get-env {:as :edn, :return :explain} :taoensso.telemere/rt-filters<.platform><.edn>))
;;;; Context (optional arb app-level state)
;; taoensso.telemere/*ctx*
(defn update-ctx
"Returns `new-ctx` given `old-ctx` and an update map or fn."
[old-ctx update-map-or-fn]
(enc/cond
(nil? update-map-or-fn) old-ctx
(map? update-map-or-fn) (enc/fast-merge old-ctx update-map-or-fn) ; Before ifn
(ifn? update-map-or-fn) (update-map-or-fn old-ctx)
:else
(enc/unexpected-arg! update-map-or-fn
{:context `update-ctx
:param 'update-map-or-fn
:expected '#{nil map fn}})))
;;;; Unique IDs (UIDs)
(enc/def* nanoid-readable (enc/rand-id-fn {:chars :nanoid-readable, :len 23}))

View file

@ -228,23 +228,37 @@
(is (= rv6 13)) (is (= (force (get sv6 dk)) [:n 12, :c6 15]))
(is (= @c 16) "6x run + 6x let (0x suppressed) + 4x data (2x suppressed)")]))))
(testing "Binding conveyance"
(binding [*dynamic-var* :foo]
(is (sm? (with-sig (sig! {:level :info, :data {:dynamic-var *dynamic-var*}})) {:data {:dynamic-var :foo}}))))
(testing "Dynamic context (`*ctx*`)"
(let [sv (with-sig (sig! {:level :info, :ctx "my-ctx"}))] (is (sm? sv {:ctx "my-ctx"}) "Can be set via call opt")))
(testing "Dynamic middleware (`*middleware*`)"
[(is (sm? (tel/with-middleware nil (with-sig (sig! {:level :info }))) {:level :info }) "nil middleware ~ identity")
(is (sm? (tel/with-middleware identity (with-sig (sig! {:level :info }))) {:level :info }) "nil middleware ~ identity")
(is (sm? (tel/with-middleware #(assoc % :foo 1) (with-sig (sig! {:level :info }))) {:level :info, :foo 1 }))
(is (sm? (tel/with-middleware #(assoc % :foo 1) (with-sig (sig! {:level :info, :middleware #(assoc % :foo 2)}))) {:level :info, :foo 2 }) "call > dynamic")
(is (sm? (tel/with-middleware #(assoc % :foo 1) (with-sig (sig! {:level :info, :middleware nil}))) {:level :info, :foo :submap/nx}) "call > dynamic")
(is (= (tel/with-middleware #(do nil) (with-sig (sig! {:level :info }))) nil) "return nil => suppress")
(is (sm? (tel/with-middleware #(do nil) (with-sig (sig! {:level :info, :middleware nil}))) {:level :info}) "call > dynamic")])
(testing "Call middleware"
(let [c (enc/counter)
[[rv1 _] [sv1]] (with-sigs :raw nil (sig! {:level :info, :run (c), :middleware (tel/comp-middleware #(assoc % :m1 (c)) #(assoc % :m2 (c)))}))
[[rv2 _] [sv2]] (with-sigs :raw nil (sig! {:level :info, :run (c), :middleware (tel/comp-middleware #(assoc % :m1 (c)) #(assoc % :m2 (c))), :allow? false}))
[[rv3 _] [sv3]] (with-sigs :raw nil (sig! {:level :info, :run (c), :middleware (tel/comp-middleware #(assoc % :m1 (c)) #(assoc % :m2 (c)))}))
[[rv4 _] [sv4]] (with-sigs :raw nil (sig! {:level :info, :middleware (fn [_] "signal-value")}))]
[[rv4 _] [sv4]] (with-sigs :raw nil (sig! {:level :info, :middleware (fn [_] "signal-value")}))
[[rv5 _] [sv5]] (with-sigs :raw nil (sig! {:level :info, :middleware (fn [_] nil)}))]
[(is (= rv1 0)) (is (sm? sv1 {:m1 1 :m2 2}))
(is (= rv2 3)) (is (nil? sv2))
(is (= rv3 4)) (is (sm? sv3 {:m1 5 :m2 6}))
(is (= rv4 true)) (is (= sv4 "signal-value"))
(is (= rv5 true)) (is (nil? sv5))
(is (= @c 7) "3x run + 4x middleware")]))
(testing "Binding conveyance"
(binding [*dynamic-var* :foo]
(is (sm? (with-sig (sig! {:level :info, :data {:dynamic-var *dynamic-var*}})) {:data {:dynamic-var :foo}}))))
#?(:clj
(testing "Printing"
(let [sv1 (with-sig (sig! {:level :info, :run (+ 1 2), :my-k1 :my-v1}))
@ -398,17 +412,6 @@
(is (= @sv_ :nx))
(is (sm? @error_ {:handler-id :hid1, :error pex1?}))])])])))
(deftest _ctx
(testing "Context (`*ctx*`)"
[(is (= (binding [tel/*ctx* "my-ctx"] tel/*ctx*) "my-ctx") "Supports manual `binding`")
(is (= (tel/with-ctx "my-ctx" tel/*ctx*) "my-ctx") "Supports any data type")
(is (= (tel/with-ctx "my-ctx1" (tel/with-ctx+ nil tel/*ctx*)) "my-ctx1") "nil update => keep old-ctx")
(is (= (tel/with-ctx "my-ctx1" (tel/with-ctx+ (fn [old] [old "my-ctx2"]) tel/*ctx*)) ["my-ctx1" "my-ctx2"]) "fn update => apply")
(is (= (tel/with-ctx {:a :A1 :b :B1} (tel/with-ctx+ {:a :A2 :c :C2} tel/*ctx*)) {:a :A2 :b :B1 :c :C2}) "map update => merge")
(let [sv (with-sig (sig! {:level :info, :ctx "my-ctx"}))] (is (sm? sv {:ctx "my-ctx"}) "Can be set via call opt"))]))
(deftest _tracing
(testing "Tracing"
[(let [sv (with-sig (sig! {:level :info }))] (is (sm? sv {:parent nil})))