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
starfederation.datastar.clojure.utils/transient-> clojure.core/->
starfederation.datastar.clojure.utils/def-clone clojure.core/def}
starfederation.datastar.clojure.utils/transient-> clojure.core/->}
:hooks
{:analyze-call
{test.utils/with-server hooks.test-hooks/with-server}}

View File

@ -1,5 +1,24 @@
# 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
### Changed

View File

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

View File

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

View File

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

View File

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