From 6cd211f294f553b6cb5716e7c36ad48b0eea2a09 Mon Sep 17 00:00:00 2001 From: liquidz Date: Sun, 29 Dec 2024 08:06:09 +0900 Subject: [PATCH] fix: Update elin.interceptor.tap/initialize to call tap-handler for intercepting tapped values --- resources/config.edn | 4 +- src/elin/interceptor/tap.clj | 94 ++++++++++++++++++++++++++++-------- 2 files changed, 77 insertions(+), 21 deletions(-) diff --git a/resources/config.edn b/resources/config.edn index 0c628da..3fa6ddc 100644 --- a/resources/config.edn +++ b/resources/config.edn @@ -35,8 +35,8 @@ elin.interceptor.nrepl/normalize-path {} elin.interceptor.nrepl/progress {} elin.interceptor.output/print-output {} - elin.interceptor.tap/initialize {} - elin.interceptor.tap/access-tapped-values {}] + elin.interceptor.tap/initialize {:max-store-size 10} + elin.interceptor.tap/access-tapped-values {:var-name "*tapped*"}] :config-map {elin.interceptor.evaluate/set-eval-result-to-virtual-text {:format "=> {{{result}}}" :highlight "DiffText" diff --git a/src/elin/interceptor/tap.clj b/src/elin/interceptor/tap.clj index 6c0beee..246abd8 100644 --- a/src/elin/interceptor/tap.clj +++ b/src/elin/interceptor/tap.clj @@ -3,12 +3,11 @@ [clojure.string :as str] [elin.constant.interceptor :as e.c.interceptor] [elin.function.evaluate :as e.f.evaluate] - [exoscale.interceptor :as ix]) - (:import - (java.time LocalDateTime))) + [elin.util.interceptor :as e.u.interceptor] + [exoscale.interceptor :as ix])) (def ^:private ns-sym - 'elin.interceptor.tap) + (gensym "elin.interceptor.tap.")) (def ^:private tap-fn-sym 'catch-tapped!) @@ -17,10 +16,39 @@ (gensym "elin-tapped")) (defn- initialize-code - [] + [{:keys [http-server-port max-store-size]}] (str `(do (in-ns '~ns-sym) (refer-clojure) + + (defn datafy# + [x#] + (clojure.walk/prewalk + (fn [v#] + (cond + (map? v#) (update-vals v# datafy#) + (list? v#) (map datafy# v#) + (vector? v#) (mapv datafy# v#) + :else (clojure.core.protocols/datafy v#))) + x#)) + + (defn tap-handler-request# + [value#] + (try + (let [uri# (java.net.URI/create + (str "http://localhost:" ~http-server-port "/api/v1")) + body# (format "{\"method\": \"elin.handler.tap/tapped\", \"params\": [%s]}" + (pr-str (pr-str value#))) + client# (java.net.http.HttpClient/newHttpClient) + req# (-> (java.net.http.HttpRequest/newBuilder) + (.uri uri#) + (.header "Content-Type" "application/json") + (.POST (java.net.http.HttpRequest$BodyPublishers/ofString body#)) + (.build))] + + (.send client# req# (java.net.http.HttpResponse$BodyHandlers/ofString))) + (catch Exception _# nil))) + (def ~tapped-atom-sym (atom [])) (try @@ -29,26 +57,54 @@ (defn ~tap-fn-sym [x#] - (swap! ~tapped-atom-sym conj {:id (str (random-uuid)) - :time (str (LocalDateTime/now)) - :value (clojure.core.protocols/datafy x#)})) + (let [value# (datafy# x#)] + (tap-handler-request# value#) + (when (<= ~max-store-size (count (deref ~tapped-atom-sym))) + (swap! ~tapped-atom-sym (fn [v#] (drop-last 1 v#)))) + (swap! ~tapped-atom-sym (fn [v#] + (cons {:id (str (random-uuid)) + :time (str (java.time.LocalDateTime/now)) + :value value#} + v#))))) (try (add-tap ~tap-fn-sym) (catch Exception _# nil))))) (def initialize - "Defines a tap function and adds it." + "Defines a tap function and adds it. + + .Configuration + [%autowidth.stretch] + |=== + | key | type | description + + | max-store-size | integer | The maximum number of values to store when tapped. Defautl value is `10`. + |===" {:kind e.c.interceptor/connect - :leave (-> (fn [ctx] - (e.f.evaluate/evaluate-code ctx (initialize-code))) + :leave (-> (fn [{:as ctx :component/keys [handler]}] + (let [config (e.u.interceptor/config ctx #'initialize) + http-server-port (get-in handler [:initialize :export "g:elin_http_server_port"]) + code (initialize-code {:max-store-size (:max-store-size config) + :http-server-port http-server-port})] + (e.f.evaluate/evaluate-code ctx code))) (ix/discard))}) (def access-tapped-values - "Enables access to tapped values from a specific symbol." - {:kind e.c.interceptor/evaluate - :enter (-> (fn [ctx] - (let [var-sym (symbol (name ns-sym) - (name tapped-atom-sym)) - var-code (str `(deref ~var-sym))] - (update ctx :code #(str/replace % #"\*tapped\*" var-code)))) - (ix/when #(str/includes? (:code %) "*tapped*")))}) + "Enables access to tapped values from a specific symbol. + + .Configuration + [%autowidth.stretch] + |=== + | key | type | description + + | var-name | string | The var name to access tapped values. Default value is `\\*tapped*`. + |===" + (let [get-target-name #(-> (e.u.interceptor/config % #'access-tapped-values) + (:var-name))] + {:kind e.c.interceptor/evaluate + :enter (-> (fn [ctx] + (let [target-name (get-target-name ctx) + var-code (str `(deref ~(symbol (name ns-sym) + (name tapped-atom-sym))))] + (update ctx :code #(str/replace % target-name var-code)))) + (ix/when #(str/includes? (:code %) (get-target-name %))))}))