Fix: added proper clj-kondo config fixing unresolved vars warnings

Fix: handling of the HTTP keep-alive header
Refactor: simpler concurrency handling in one test.
This commit is contained in:
Jeremy Schoffen 2025-04-07 14:01:24 +02:00
parent 3b18b23a1f
commit 73b1389971
10 changed files with 71 additions and 43 deletions

View File

@ -1,6 +1,5 @@
{:lint-as {fr.jeremyschoffen.datastar.utils/defroutes clojure.core/def {:lint-as {fr.jeremyschoffen.datastar.utils/defroutes clojure.core/def
starfederation.datastar.clojure.utils/transient-> clojure.core/-> starfederation.datastar.clojure.utils/transient-> clojure.core/->}
starfederation.datastar.clojure.utils/def-clone clojure.core/def}
:hooks :hooks
{:analyze-call {:analyze-call
{test.utils/with-server hooks.test-hooks/with-server}} {test.utils/with-server hooks.test-hooks/with-server}}

View File

@ -1,5 +1,24 @@
# Release notes for the Clojure SDK # Release notes for the Clojure SDK
## 2025-04-07
### Added
- The vars holding keywords (like `on-open`) in the adapter namespaces were not
properly recognized by Clj-kondo. This generated `unresolved var` warnings. A
specific Clj-kondo config has been added to fix these warnings.
### Fixed
- The HTTP version detection that determines whether to add the
`Connection keep-alive` HTTP header has been changed. The header is now
properly added for versions older than `HTTP/1.1`.
### Changed
- Bumped the ring version from `1.13.0` to `1.14.1`. This encourages users
to use Jetty 12 when using ring jetty adapter.
## 2025-03-31 ## 2025-03-31
### Changed ### Changed

View File

@ -1,2 +1,2 @@
{:paths ["src/main"] {:paths ["src/main"]
:deps {org.ring-clojure/ring-core-protocols {:mvn/version "1.13.0"}}} :deps {org.ring-clojure/ring-core-protocols {:mvn/version "1.14.1"}}}

View File

@ -1,6 +1,7 @@
{:paths ["sdk/src/main"] {:paths []
:deps {io.github.paintparty/fireworks {:mvn/version "0.10.4"} :deps {sdk/sdk {:local/root "./sdk"}
io.github.paintparty/fireworks {:mvn/version "0.10.4"}
com.taoensso/telemere {:mvn/version "1.0.0-RC3"} com.taoensso/telemere {:mvn/version "1.0.0-RC3"}
com.aayushatharva.brotli4j/brotli4j {:mvn/version "1.18.0"}} com.aayushatharva.brotli4j/brotli4j {:mvn/version "1.18.0"}}
@ -42,7 +43,7 @@
:http-kit {:extra-deps {sdk/adapter-http-kit {:local/root "./adapter-http-kit"}}} :http-kit {:extra-deps {sdk/adapter-http-kit {:local/root "./adapter-http-kit"}}}
:ring-jetty {:extra-deps {sdk/adapter-ring {:local/root "./adapter-ring"} :ring-jetty {:extra-deps {sdk/adapter-ring {:local/root "./adapter-ring"}
ring/ring-jetty-adapter {:mvn/version "1.13.0"}}} ring/ring-jetty-adapter {:mvn/version "1.14.1"}}}
:ring-rj9a {:extra-deps {sdk/adapter-ring {:local/root "./adapter-ring"} :ring-rj9a {:extra-deps {sdk/adapter-ring {:local/root "./adapter-ring"}
info.sunng/ring-jetty9-adapter {:mvn/version "0.36.1"}}} info.sunng/ring-jetty9-adapter {:mvn/version "0.36.1"}}}

View File

@ -1,2 +1,2 @@
{:paths ["src/main"]} {:paths ["src/main" "resources"]}

View File

@ -0,0 +1,3 @@
{:lint-as
{starfederation.datastar.clojure.utils/def-clone clojure.core/def}}

View File

@ -134,15 +134,17 @@
(-> (transient {}) (-> (transient {})
(u/merge-transient! sse/base-SSE-headers) (u/merge-transient! sse/base-SSE-headers)
(cond-> (cond->
(sse/http1? ring-request) (assoc! "Connection" "keep-alive",) (sse/add-keep-alive? ring-request) (assoc! "Connection" "keep-alive",)
encoding (assoc! "Content-Encoding" encoding)) encoding (assoc! "Content-Encoding" encoding))
(u/merge-transient! (:headers opts)) (u/merge-transient! (:headers opts))
persistent!))) persistent!)))
(comment (comment
(headers {:protocol "HTTP/2"} {}) (headers {:protocol "HTTP/1.0"} {})
(headers {:protocol "HTTP/2"} {write-profile {content-encoding "br"}})) (headers {:protocol "HTTP/1.1"} {})
(headers {:protocol "HTTP/2"} {})
(headers {:protocol "HTTP/2"} {write-profile {content-encoding "br"}}))
;; ----------------------------------------------------------------------------- ;; -----------------------------------------------------------------------------
;; Utilities for wrapping an OutputStream ;; Utilities for wrapping an OutputStream

View File

@ -15,11 +15,16 @@
"Content-Type" "text/event-stream"}) "Content-Type" "text/event-stream"})
(defn http1? [ring-request] (defn add-keep-alive? [ring-request]
(let [protocol (:protocol ring-request)] (let [protocol (:protocol ring-request)]
(or (or (nil? protocol)
(nil? protocol) (neg? (compare protocol "HTTP/1.1")))))
(= "HTTP/1.1" protocol))))
(comment
(add-keep-alive? {:protocol "HTTP/0.9"})
(add-keep-alive? {:protocol "HTTP/1.0"})
(add-keep-alive? {:protocol "HTTP/1.1"})
(add-keep-alive? {:protocol "HTTP/2"}))
(defn headers (defn headers
@ -41,7 +46,7 @@
(-> (transient {}) (-> (transient {})
(u/merge-transient! base-SSE-headers) (u/merge-transient! base-SSE-headers)
(cond-> (cond->
(http1? ring-request) (assoc! "Connection" "keep-alive",)) (add-keep-alive? ring-request) (assoc! "Connection" "keep-alive",))
(u/merge-transient! (:headers opts)) (u/merge-transient! (:headers opts))
persistent!)) persistent!))

View File

@ -55,6 +55,3 @@
(u/clear-terminal!) (u/clear-terminal!)
(u/reboot-hk-server! #'handler)) (u/reboot-hk-server! #'handler))

View File

@ -11,9 +11,7 @@
[starfederation.datastar.clojure.adapter.common :as ac] [starfederation.datastar.clojure.adapter.common :as ac]
[starfederation.datastar.clojure.api :as d*] [starfederation.datastar.clojure.api :as d*]
[starfederation.datastar.clojure.api.sse :as sse] [starfederation.datastar.clojure.api.sse :as sse]
[test.utils :as u]) [test.utils :as u]))
(:import
java.util.concurrent.CountDownLatch))
(def ^:dynamic *ctx* nil) (def ^:dynamic *ctx* nil)
@ -93,7 +91,8 @@
(println "Killing agents") (println "Killing agents")
(shutdown-agents))))) (shutdown-agents)))))
(install-shutdown-hooks!) (defonce _ (install-shutdown-hooks!))
;; ----------------------------------------------------------------------------- ;; -----------------------------------------------------------------------------
;; Generic counters tests ;; Generic counters tests
;; ----------------------------------------------------------------------------- ;; -----------------------------------------------------------------------------
@ -143,13 +142,12 @@
(defn- ->persistent-sse-handler (defn- ->persistent-sse-handler
"Make a ring handler that puts a sse gen into an atom for use later. "Make a ring handler that puts a sse gen into an atom for use later.
Counts down an latch to allow the tests to continue." Counts down an latch to allow the tests to continue."
[->sse-response !conn ^CountDownLatch latch] [->sse-response !conn]
(fn handler (fn handler
([req] ([req]
(->sse-response req (->sse-response req
{ac/on-open (fn [sse-gen] {ac/on-open (fn [sse-gen]
(reset! !conn sse-gen) (deliver !conn sse-gen))}))
(.countDown latch))}))
([req respond _raise] ([req respond _raise]
(respond (handler req))))) (respond (handler req)))))
@ -159,11 +157,9 @@
We put together an atom to store a sse generator, a countdown latch and a We put together an atom to store a sse generator, a countdown latch and a
ring handler hooked to them." ring handler hooked to them."
[->sse-response] [->sse-response]
(let [!conn (atom nil) (let [!conn (promise)
latch (CountDownLatch. 1) handler (->persistent-sse-handler ->sse-response !conn)]
handler (->persistent-sse-handler ->sse-response !conn latch)]
{:!conn !conn {:!conn !conn
:latch latch
:handler handler})) :handler handler}))
@ -177,8 +173,7 @@
{:keys [!conn latch handler]} (setup-persistent-see-state ->sse-response)] {:keys [!conn latch handler]} (setup-persistent-see-state ->sse-response)]
(u/with-server server handler (dissoc server-opts :get-port) (u/with-server server handler (dissoc server-opts :get-port)
(binding [*ctx* {:port (get-port server) (binding [*ctx* {:port (get-port server)
:!conn !conn :!conn !conn}]
:latch latch}]
(f)))))) (f))))))
@ -188,13 +183,14 @@
(defn run-persistent-sse-test! [] (defn run-persistent-sse-test! []
(let [{:keys [port latch !conn]} *ctx* (let [{:keys [port !conn]} *ctx*
response (http/request {:url (u/url port "")})] response (http/request {:url (u/url port "")})
(.await ^CountDownLatch latch) sse-gen (deref !conn 100 nil)]
(let [sse-gen @!conn] (when-not sse-gen
(persistent-see-send-events! sse-gen) (throw (ex-info "The handler did not deliver the persistent sse-gen." {})))
(d*/close-sse! sse-gen) (persistent-see-send-events! sse-gen)
(deref response 10 :error)))) (d*/close-sse! sse-gen)
(deref response 10 :error)))
@ -202,12 +198,18 @@
(lt/expect (= (:status response) 200))) (lt/expect (= (:status response) 200)))
(def SSE-headers-1 (update-keys (sse/headers {}) (comp keyword string/lower-case))) (defn ->headers [req]
#_{:clj-kondo/ignore true} (-> req
(def SSE-headers-2+ (update-keys (sse/headers {:protocol "2"}) (comp keyword string/lower-case))) sse/headers
(update-keys (comp keyword string/lower-case))))
(def SSE-headers-1-dot-0 (->headers {}))
(def SSE-headers-1-dot-1 (->headers {:protocol "HTTP/1.1"}))
(def SSE-headers-2+ (->headers {:protocol "HTTP/2"}))
(defn p-sse-http1-headers-ok? [response] (defn p-sse-http1-headers-ok? [response]
(lt/expect (mc/match? SSE-headers-1 (:headers response)))) (lt/expect (mc/match? SSE-headers-1-dot-1 (:headers response))))
(def expected-p-sse-res-body (def expected-p-sse-res-body