diff --git a/frameworks/aleph/Dockerfile b/frameworks/aleph/Dockerfile index 2f949c64d..ec7a78fee 100644 --- a/frameworks/aleph/Dockerfile +++ b/frameworks/aleph/Dockerfile @@ -1,4 +1,4 @@ -FROM clojure:temurin-21-lein AS builder +FROM clojure:temurin-26-lein-trixie AS builder WORKDIR /app COPY project.clj ./ COPY resources ./resources @@ -6,7 +6,7 @@ RUN lein deps COPY src ./src RUN lein with-profile uberjar uberjar -FROM eclipse-temurin:25-jre +FROM eclipse-temurin:26-jre RUN mkdir -p /data/static WORKDIR /app COPY --from=builder /app/target/aleph-bench-0.1.0-standalone.jar /app/app.jar diff --git a/frameworks/aleph/meta.json b/frameworks/aleph/meta.json index f56338c25..9d72b6f96 100644 --- a/frameworks/aleph/meta.json +++ b/frameworks/aleph/meta.json @@ -15,11 +15,13 @@ "noisy", "short-lived", "mixed", + "json-tls", "api-4", "api-16", "async-db", "sync-db", "static", - "tcp-frag" + "tcp-frag", + "crud" ] } \ No newline at end of file diff --git a/frameworks/aleph/project.clj b/frameworks/aleph/project.clj index 71698bacf..0c7acc921 100644 --- a/frameworks/aleph/project.clj +++ b/frameworks/aleph/project.clj @@ -24,14 +24,14 @@ io.netty/netty-transport-native-kqueue io.netty/netty-transport-native-unix-common]] [io.netty/netty-all "4.2.12.Final"] - [org.clojars.jj/tassu "1.0.3"] + [org.clojars.jj/tassu "1.0.4"] [org.clojars.jj/boa-sql "1.0.10"] [org.clojars.jj/async-boa-sql "1.0.10"] [org.clojars.jj/next-jdbc-adapter "1.0.10"] [org.clojars.jj/vertx-pg-client-async-boa-adapter "1.0.1"] - [org.xerial/sqlite-jdbc "3.49.1.0"] [metosin/jsonista "1.0.0"] - [com.github.seancorfield/next.jdbc "1.3.1093"]] + + [org.clojure/core.cache "1.2.263"]] :main ^:skip-aot aleph-bench.core diff --git a/frameworks/aleph/resources/sql/crud-create b/frameworks/aleph/resources/sql/crud-create new file mode 100644 index 000000000..5990ff0aa --- /dev/null +++ b/frameworks/aleph/resources/sql/crud-create @@ -0,0 +1 @@ +INSERT INTO items (id, name, category, price, quantity, active, tags, rating_score, rating_count) VALUES (:id, :name, :category, :price, :quantity, true, '["bench"]', 0, 0) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, price = EXCLUDED.price, quantity = EXCLUDED.quantity RETURNING id diff --git a/frameworks/aleph/resources/sql/crud-list b/frameworks/aleph/resources/sql/crud-list new file mode 100644 index 000000000..f4b11de3b --- /dev/null +++ b/frameworks/aleph/resources/sql/crud-list @@ -0,0 +1 @@ +SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count FROM items WHERE category = :category ORDER BY id LIMIT :limit OFFSET :offset diff --git a/frameworks/aleph/resources/sql/crud-read b/frameworks/aleph/resources/sql/crud-read new file mode 100644 index 000000000..46a9e52b8 --- /dev/null +++ b/frameworks/aleph/resources/sql/crud-read @@ -0,0 +1 @@ +SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count FROM items WHERE id = :id LIMIT 1 diff --git a/frameworks/aleph/resources/sql/crud-update b/frameworks/aleph/resources/sql/crud-update new file mode 100644 index 000000000..098701633 --- /dev/null +++ b/frameworks/aleph/resources/sql/crud-update @@ -0,0 +1 @@ +UPDATE items SET name = :name, price = :price, quantity = :quantity WHERE id = :id RETURNING id \ No newline at end of file diff --git a/frameworks/aleph/src/aleph_bench/core.clj b/frameworks/aleph/src/aleph_bench/core.clj index b58a34dd7..b270c2d89 100644 --- a/frameworks/aleph/src/aleph_bench/core.clj +++ b/frameworks/aleph/src/aleph_bench/core.clj @@ -1,24 +1,23 @@ (ns aleph-bench.core (:require [aleph.http :as http] [aleph.netty :as netty] + [clojure.core.cache :as cache] [clojure.java.io :as io] [clojure.string :as str] [jj.sql.async-boa :as async-boa] - [jj.sql.boa :as boa] - [jj.sql.boa.query.next-jdbc :refer [->NextJdbcAdapter]] [jj.sql.boa.query.vertx-pg :as vertx-adapter] - [jj.tassu :refer [GET POST route]] + [jj.tassu :refer [GET POST PUT route]] [jsonista.core :as json] [manifold.deferred :as d] - [manifold.stream :as s] - [next.jdbc :as jdbc]) + [manifold.stream :as s]) (:import (io.netty.buffer ByteBuf PooledByteBufAllocator) (io.netty.channel ChannelOption) (io.netty.handler.codec.http HttpContentCompressor) + (io.netty.handler.ssl SslContextBuilder) (io.vertx.core Vertx) (io.vertx.pgclient PgBuilder PgConnectOptions) (io.vertx.sqlclient PoolOptions) - (java.io ByteArrayOutputStream ) + (java.io ByteArrayOutputStream FileInputStream) (java.net URI)) (:gen-class)) @@ -33,25 +32,31 @@ (def ^:private ^:const empty-db-body "{\"items\":[],\"count\":0}") (def ^:private ^:const dataset-path "/data/dataset.json") (def ^:private ^:const dataset-large-path "/data/dataset-large.json") -(def ^:private ^:const db-path "/data/benchmark.db") (def ^:private ^:const param-min "min") (def ^:private ^:const param-max "max") (def ^:private ^:const param-limit "limit") (def ^:private ^:const param-m "m") (def ^:private ^:const pg-prefix "postgres://") (def ^:private ^:const pg-replace "postgresql://") +(def ^:private ^:const plain-port 8080) +(def ^:private ^:const tls-port 8081) +(def ^:private ^:const tls-cert-default "/certs/server.crt") +(def ^:private ^:const tls-key-default "/certs/server.key") (def ^:private json-headers {hdr-ct ct-json hdr-server server-name}) (def ^:private text-headers {hdr-ct ct-text hdr-server server-name}) +(def ^:private crud-hit-headers {hdr-ct ct-json hdr-server server-name "X-Cache" "HIT"}) +(def ^:private crud-miss-headers {hdr-ct ct-json hdr-server server-name "X-Cache" "MISS"}) (def ^:private empty-db-response {:status 200 :headers json-headers :body empty-db-body}) +(def ^:private ^:const extension-map + {".css" "text/css" ".js" "application/javascript" ".html" "text/html" + ".woff2" "font/woff2" ".svg" "image/svg+xml" ".webp" "image/webp" ".json" ct-json}) + (defn- load-json [path] (when (.exists (io/file path)) (json/read-value (slurp path) json/keyword-keys-object-mapper))) -(defn- process-item [item ^long m] - (assoc item :total (* (:price item) (:quantity item) m))) - (defn- parse-qs [^String qs] (when qs (loop [i 0 m (transient {})] @@ -73,23 +78,29 @@ end (if (neg? amp) (.length qs) amp) eq (.indexOf qs (int \=) i)] (if (and (>= eq 0) (< eq end)) - (recur (inc end) - (+ sum (long (try (Long/parseLong (subs qs (inc eq) end)) - (catch Exception _ 0))))) + (recur (inc end) (+ sum (long (try (Long/parseLong (subs qs (inc eq) end)) (catch Exception _ 0))))) (recur (inc end) sum))))))) -(defn- json-response [data] - {:status 200 :headers json-headers :body (json/write-value-as-string data)}) - -(defn- text-response [s] - {:status 200 :headers text-headers :body (str s)}) - (defn- parse-long-param [params k default] (try (Long/parseLong (get params k)) (catch Exception _ default))) (defn- parse-double-param [params k default] (try (Double/parseDouble (get params k)) (catch Exception _ default))) +(defn- process-item [item ^long m] + (assoc item :total (* (:price item) (:quantity item) m))) + +(defn- get-content-type [^String name] + (let [dot-index (.lastIndexOf name ^String dot) + ext (if (>= dot-index 0) (subs name dot-index) "")] + (get extension-map ext ct-octet))) + +(defn- json-response [data] + {:status 200 :headers json-headers :body (json/write-value-as-string data)}) + +(defn- text-response [s] + {:status 200 :headers text-headers :body (str s)}) + (defn- read-body-bytes [body] (if (nil? body) (d/success-deferred (byte-array 0)) @@ -107,26 +118,219 @@ body) (fn [^ByteArrayOutputStream baos] (.toByteArray baos))))) -(def ^:private ^:const extension-map - {".css" "text/css" - ".js" "application/javascript" - ".html" "text/html" - ".woff2" "font/woff2" - ".svg" "image/svg+xml" - ".webp" "image/webp" - ".json" ct-json}) - -(defn- get-content-type [^String name] - (let [dot-index (.lastIndexOf name ^String dot) - ext (if (>= dot-index 0) (subs name dot-index) "")] - (get extension-map ext ct-octet))) - -(defn- transform-row [row parse-tags parse-active] +(defn- transform-pg-row [row] {:id (:id row) :name (:name row) :category (:category row) - :price (:price row) :quantity (:quantity row) :active (parse-active (:active row)) - :tags (parse-tags (:tags row)) + :price (:price row) :quantity (:quantity row) :active (:active row) + :tags (json/read-value (str (:tags row))) :rating {:score (:rating_score row) :count (:rating_count row)}}) +(defn- transform-crud-row [row] + {:id (:id row) :name (:name row) :category (:category row) + :price (long (:price row)) :quantity (long (:quantity row)) :active (:active row) + :tags (json/read-value (str (:tags row))) + :rating {:score (long (:rating_score row)) :count (long (:rating_count row))}}) + +(def crud-cache (atom (cache/ttl-cache-factory {} :ttl 200))) + +(defn- crud-cache-get [id] + (let [c @crud-cache] + (when (cache/has? c id) + (swap! crud-cache cache/hit id) + (cache/lookup @crud-cache id)))) + +(defn- crud-cache-set [id v] + (swap! crud-cache #(cache/miss % id v))) + +(defn- crud-cache-evict [id] + (swap! crud-cache cache/evict id)) + +(def ^:private adapter (vertx-adapter/->VertxPgAdapter)) +(def ^:private pg-query-fn (async-boa/build-async-query adapter "sql/pg-query")) +(def ^:private crud-list-q (async-boa/build-async-query adapter "sql/crud-list")) +(def ^:private crud-read-q (async-boa/build-async-query adapter "sql/crud-read")) +(def ^:private crud-create-q (async-boa/build-async-query adapter "sql/crud-create")) +(def ^:private crud-update-q (async-boa/build-async-query adapter "sql/crud-update")) + +(defn- build-ssl-context [] + (let [cert-path (or (System/getenv "TLS_CERT") tls-cert-default) + key-path (or (System/getenv "TLS_KEY") tls-key-default) + cert-file (io/file cert-path) + key-file (io/file key-path)] + (when (and (.exists cert-file) (.exists key-file)) + (try + (-> (SslContextBuilder/forServer cert-file key-file) + (.build)) + (catch Exception e + (println "TLS init failed:" (.getMessage e)) + nil))))) + +(defn- init-pg-pool [] + (when-let [url (System/getenv "DATABASE_URL")] + (try + (let [uri (URI. (str/replace url pg-prefix pg-replace)) + host (.getHost uri) + port (if (pos? (.getPort uri)) (.getPort uri) 5432) + db (subs (.getPath uri) 1) + [user pass] (str/split (.getUserInfo uri) #":" 2) + max-conn (try (Integer/parseInt (System/getenv "DATABASE_MAX_CONN")) + (catch Exception _ 256)) + connect-opts (-> (PgConnectOptions.) + (.setHost host) (.setPort port) (.setDatabase db) + (.setUser user) (.setPassword (or pass ""))) + pool-opts (-> (PoolOptions.) (.setMaxSize max-conn)) + vertx (Vertx/vertx)] + (-> (PgBuilder/pool) + (.with pool-opts) + (.connectingTo connect-opts) + (.using vertx) + (.build))) + (catch Throwable t + (println "PG init failed:" (.getMessage t)) + nil)))) + +(defn- handle-baseline-get [req] + (text-response (sum-params (:query-string req)))) + +(defn- handle-baseline-post [req] + (let [s (sum-params (:query-string req))] + (d/chain (read-body-bytes (:body req)) + (fn [^bytes bs] + (let [n (try (Long/parseLong (str/trim (String. bs))) (catch Exception _ 0))] + (text-response (+ s n))))))) + +(defn- handle-json [dataset req] + (let [count (try (Long/parseLong (get-in req [:params :count])) (catch Exception _ 50)) + count (min count (long (clojure.core/count dataset))) + params (parse-qs (:query-string req)) + m (parse-long-param params param-m 1) + items (mapv #(process-item % m) (subvec dataset 0 count))] + {:status 200 :headers json-headers + :body (json/write-value-as-string {:items items :count (clojure.core/count items)})})) + +(defn- handle-upload [req] + (d/chain (read-body-bytes (:body req)) + (fn [^bytes bs] (text-response (alength bs))))) + +(defn- handle-async-db [pg-pool req] + (let [params (parse-qs (:query-string req)) + min-p (parse-double-param params param-min 10.0) + max-p (parse-double-param params param-max 50.0) + limit (parse-long-param params param-limit 50) + dfd (d/deferred)] + (pg-query-fn pg-pool {:min min-p :max max-p :limit limit} + (fn [rows] + (let [items (mapv transform-pg-row rows)] + (d/success! dfd (json-response {:items items :count (clojure.core/count items)})))) + (fn [_] (d/success! dfd empty-db-response))) + dfd)) + +(defn- handle-crud-list [pg-pool req] + (let [params (parse-qs (:query-string req)) + category (or (get params "category") "electronics") + page (max 1 (parse-long-param params "page" 1)) + limit (max 1 (min 50 (parse-long-param params "limit" 10))) + offset (* (dec page) limit) + dfd (d/deferred)] + (crud-list-q pg-pool {:category category :limit limit :offset offset} + (fn [rows] + (let [items (mapv transform-crud-row rows)] + (d/success! dfd (json-response {:items items :total (clojure.core/count items) :page page :limit limit})))) + (fn [_] (d/success! dfd (json-response {:items [] :total 0 :page page :limit limit})))) + dfd)) + +(defn- handle-crud-read [pg-pool req] + (let [id (try (Long/parseLong (get-in req [:params :id])) (catch Exception _ nil))] + (if (nil? id) + {:status 404 :headers json-headers :body not-found-body} + (if-let [cached (crud-cache-get id)] + {:status 200 :headers crud-hit-headers :body cached} + (let [dfd (d/deferred)] + (crud-read-q pg-pool {:id id} + (fn [rows] + (if-let [row (first rows)] + (let [json-str (json/write-value-as-string (transform-crud-row row))] + (crud-cache-set id json-str) + (d/success! dfd {:status 200 :headers crud-miss-headers :body json-str})) + (d/success! dfd {:status 404 :headers json-headers :body not-found-body}))) + (fn [_] (d/success! dfd {:status 404 :headers json-headers :body not-found-body}))) + dfd))))) + +(defn- handle-crud-create [pg-pool req] + (d/chain (read-body-bytes (:body req)) + (fn [^bytes bs] + (let [body (json/read-value (String. bs) json/keyword-keys-object-mapper) + id (:id body) + nm (or (:name body) "New Product") + category (or (:category body) "test") + price (or (:price body) 0) + quantity (or (:quantity body) 0) + dfd (d/deferred)] + (crud-create-q pg-pool {:id id :name nm :category category :price price :quantity quantity} + (fn [rows] + (d/success! dfd {:status 201 :headers json-headers + :body (json/write-value-as-string + {:id (:id (first rows)) :name nm :category category :price price :quantity quantity})})) + (fn [_] (d/success! dfd {:status 500 :headers json-headers :body "{\"error\":\"insert failed\"}"}))) + dfd)))) + +(defn- handle-crud-update [pg-pool req] + (let [id (try (Long/parseLong (get-in req [:params :id])) (catch Exception _ nil))] + (if (nil? id) + {:status 404 :headers json-headers :body not-found-body} + (d/chain (read-body-bytes (:body req)) + (fn [^bytes bs] + (let [body (json/read-value (String. bs) json/keyword-keys-object-mapper) + nm (or (:name body) "Updated") + price (or (:price body) 0) + quantity (or (:quantity body) 0) + dfd (d/deferred)] + (crud-update-q pg-pool {:name nm :price price :quantity quantity :id id} + (fn [rows] + (if (seq rows) + (do (crud-cache-evict id) + (d/success! dfd {:status 200 :headers json-headers + :body (json/write-value-as-string {:id id :name nm :price price :quantity quantity})})) + (d/success! dfd {:status 404 :headers json-headers :body not-found-body}))) + (fn [_] (d/success! dfd {:status 404 :headers json-headers :body not-found-body}))) + dfd)))))) + +(defn- handle-static [req] + (let [name (get-in req [:params :filename]) + path (str "/data" (:uri req)) + f (io/file path)] + (if (.isFile f) + {:status 200 :headers {hdr-ct (get-content-type name) hdr-server server-name} :body (FileInputStream. path)} + {:status 404 :body not-found-body}))) + +(defn- build-handler [{:keys [dataset json-body compression-body pg-pool]}] + (route + {"/baseline11" [(GET handle-baseline-get) + (POST handle-baseline-post)] + "/json/:count" [(GET (fn [req] (handle-json dataset req)))] + "/json" [(GET (fn [_] {:status 200 :headers json-headers :body json-body}))] + "/compression" [(GET (fn [_] {:status 200 :headers json-headers :body compression-body}))] + "/upload" [(POST handle-upload)] + "/async-db" [(GET (fn [req] (handle-async-db pg-pool req)))] + "/crud/items" [(GET (fn [req] (handle-crud-list pg-pool req))) + (POST (fn [req] (handle-crud-create pg-pool req)))] + "/crud/items/:id" [(GET (fn [req] (handle-crud-read pg-pool req))) + (PUT (fn [req] (handle-crud-update pg-pool req)))] + "/static/:filename" [(GET handle-static)] + "/" [(GET (fn [_] (text-response server-name)))]})) + +(defn- start-server! [handler port opts] + (try + (http/start-server handler (merge {:port port + :raw-stream? true + :executor :none + :bootstrap-transform (fn [bootstrap] + (.option bootstrap ChannelOption/ALLOCATOR PooledByteBufAllocator/DEFAULT) + (.childOption bootstrap ChannelOption/ALLOCATOR PooledByteBufAllocator/DEFAULT))} + opts)) + (println (str "Server running on port " port)) + (catch Exception e + (println (str "Failed to start on port " port ": " (.getMessage e)))))) + (defn -main [& _] (netty/leak-detector-level! :disabled) (let [dataset (load-json (or (System/getenv "DATASET_PATH") dataset-path)) @@ -136,108 +340,19 @@ compression-body (when large-dataset (let [items (mapv #(process-item % 1) large-dataset)] (json/write-value-as-string {:items items :count (clojure.core/count items)}))) - adapter (->NextJdbcAdapter) - sqlite-tag-parser #(json/read-value % json/keyword-keys-object-mapper) - sqlite-active #(== 1 (long %)) - pg-tag-parser #(json/read-value (str %)) - db-query-fn (when (.exists (io/file db-path)) - (boa/build-query adapter "sql/db-query")) - tl-ds (ThreadLocal.) - get-sqlite-ds (fn [] - (or (.get tl-ds) - (let [ds (jdbc/get-datasource {:dbtype "sqlite" :dbname db-path :read-only true})] - (.set tl-ds ds) - ds))) - pg-pool (when-let [url (System/getenv "DATABASE_URL")] - (try - (let [uri (URI. (str/replace url pg-prefix pg-replace)) - host (.getHost uri) - port (if (pos? (.getPort uri)) (.getPort uri) 5432) - db (subs (.getPath uri) 1) - [user pass] (str/split (.getUserInfo uri) #":" 2) - max-conn (try (Integer/parseInt (System/getenv "DATABASE_MAX_CONN")) - (catch Exception _ 256)) - connect-opts (-> (PgConnectOptions.) - (.setHost host) - (.setPort port) - (.setDatabase db) - (.setUser user) - (.setPassword (or pass ""))) - pool-opts (-> (PoolOptions.) (.setMaxSize max-conn)) - vertx (Vertx/vertx)] - (-> (PgBuilder/pool) - (.with pool-opts) - (.connectingTo connect-opts) - (.using vertx) - (.build))) - (catch Throwable t - (println "PG init failed:" (.getMessage t)) - nil))) - pg-query (when pg-pool - (async-boa/build-async-query (vertx-adapter/->VertxPgAdapter) "sql/pg-query")) - - handler - (route - {"/baseline11" [(GET (fn [req] (text-response (sum-params (:query-string req))))) - (POST (fn [req] - (let [s (sum-params (:query-string req))] - (d/chain (read-body-bytes (:body req)) - (fn [^bytes bs] - (let [n (try (Long/parseLong (str/trim (String. bs))) (catch Exception _ 0))] - (text-response (+ s n))))))))] - "/json/:count" [(GET (fn [req] - (let [count (try (Long/parseLong (get-in req [:params :count])) (catch Exception _ 50)) - count (min count (long (clojure.core/count dataset))) - params (parse-qs (:query-string req)) - m (parse-long-param params param-m 1) - items (mapv #(process-item % m) (subvec dataset 0 count))] - {:status 200 :headers json-headers :body (json/write-value-as-string {:items items :count (clojure.core/count items)})})))] - "/json" [(GET (fn [_] {:status 200 :headers json-headers :body json-body}))] - "/compression" [(GET (fn [_] {:status 200 :headers json-headers :body compression-body}))] - "/upload" [(POST (fn [req] - (d/chain (read-body-bytes (:body req)) - (fn [^bytes bs] (text-response (alength bs))))))] - "/db" [(GET (fn [req] - (if db-query-fn - (let [params (parse-qs (:query-string req)) - min-p (parse-double-param params param-min 10.0) - max-p (parse-double-param params param-max 50.0) - limit (parse-long-param params param-limit 50) - items (try (mapv #(transform-row % sqlite-tag-parser sqlite-active) (db-query-fn (get-sqlite-ds) {:min min-p :max max-p :limit limit})) - (catch Exception _ []))] - (json-response {:items items :count (clojure.core/count items)})) - empty-db-response)))] - "/async-db" [(GET (fn [req] - (if pg-query - (let [params (parse-qs (:query-string req)) - min-p (parse-double-param params param-min 10.0) - max-p (parse-double-param params param-max 50.0) - limit (parse-long-param params param-limit 50) - dfd (d/deferred)] - (pg-query pg-pool {:min min-p :max max-p :limit limit} - (fn [rows] - (let [items (mapv #(transform-row % pg-tag-parser identity) rows)] - (d/success! dfd (json-response {:items items :count (clojure.core/count items)})))) - (fn [_] (d/success! dfd empty-db-response))) - dfd) - empty-db-response)))] - "/static/:filename" [(GET (fn [req] - (let [name (get-in req [:params :filename]) - path (str "/data" (:uri req)) - f (io/file path)] - (if (.isFile f) - {:status 200 :headers {hdr-ct (get-content-type name) hdr-server server-name} :body (java.io.FileInputStream. path)} - {:status 404 :body not-found-body}))))] - "/" [(GET (fn [_] (text-response server-name)))]})] - - (http/start-server handler {:port 8080 - :raw-stream? true - :executor :none - :bootstrap-transform (fn [bootstrap] - (.option bootstrap ChannelOption/ALLOCATOR PooledByteBufAllocator/DEFAULT) - (.childOption bootstrap ChannelOption/ALLOCATOR PooledByteBufAllocator/DEFAULT)) - :pipeline-transform (fn [pipeline] - (.remove pipeline "continue-handler") - (.addBefore pipeline "request-handler" "compressor" (HttpContentCompressor.)))}) - (println "Server running on port 8080") + pg-pool (init-pg-pool) + handler (build-handler {:dataset dataset + :json-body json-body + :compression-body compression-body + :pg-pool pg-pool})] + (start-server! handler plain-port + {:pipeline-transform (fn [pipeline] + (.remove pipeline "continue-handler") + (.addBefore pipeline "request-handler" "compressor" (HttpContentCompressor.)))}) + (when-let [ssl-ctx (build-ssl-context)] + (start-server! handler tls-port + {:ssl-context ssl-ctx + :http-versions [:http1] + :pipeline-transform (fn [pipeline] + (.remove pipeline "continue-handler"))})) @(promise))) diff --git a/frameworks/ring-http-exchange/project.clj b/frameworks/ring-http-exchange/project.clj index bb47f0424..dfacdd827 100644 --- a/frameworks/ring-http-exchange/project.clj +++ b/frameworks/ring-http-exchange/project.clj @@ -9,7 +9,6 @@ [org.clojars.jj/tassu "1.0.4"] [org.clojars.jj/boa-sql "1.0.10"] [org.clojars.jj/next-jdbc-adapter "1.0.10"] - [org.xerial/sqlite-jdbc "3.49.1.0"] [org.postgresql/postgresql "42.7.5"] [metosin/jsonista "1.0.0"] [com.zaxxer/HikariCP "6.2.1"] diff --git a/frameworks/ring-http-exchange/src/ring/core.clj b/frameworks/ring-http-exchange/src/ring/core.clj index 8391d32a4..822237a25 100644 --- a/frameworks/ring-http-exchange/src/ring/core.clj +++ b/frameworks/ring-http-exchange/src/ring/core.clj @@ -6,7 +6,6 @@ [jj.sql.boa.query.next-jdbc :refer [->NextJdbcAdapter]] [jj.tassu :refer [GET POST PUT route]] [jsonista.core :as json] - [next.jdbc :as jdbc] [ring-http-exchange.core :as server] [ring-http-exchange.ssl :as ssl]) (:import (com.zaxxer.hikari HikariConfig HikariDataSource) @@ -32,7 +31,6 @@ (def ^:private ^:const dot ".") (def ^:private ^:const not-found-body "Not found") (def ^:private ^:const dataset-path "/data/dataset.json") -(def ^:private ^:const db-path "/data/benchmark.db") (def ^:private ^:const static-dir "/data/static") (def ^:private ^:const param-min "min") (def ^:private ^:const param-max "max") @@ -50,7 +48,6 @@ (def ^:private json-gzip-headers {hdr-ct ct-json hdr-ce enc-gzip hdr-server server-name}) (def ^:private text-headers {hdr-ct ct-text hdr-server server-name}) -(def ^:private sqlite-query (boa/build-query (->NextJdbcAdapter) "sql/db-query")) (def ^:private pg-query (boa/build-query (->NextJdbcAdapter) "sql/pg-query")) (def ^:private crud-list-query (boa/build-query (->NextJdbcAdapter) "sql/crud-list")) (def ^:private crud-read-query (boa/build-query (->NextJdbcAdapter) "sql/crud-read")) @@ -136,16 +133,6 @@ ext (if (>= dot-index 0) (subs name dot-index) "")] (get extension-map ext ct-octet))) -(defn- transform-sqlite-row [row] - {:id (:id row) - :name (:name row) - :category (:category row) - :price (:price row) - :quantity (:quantity row) - :active (== 1 (long (:active row))) - :tags (json/read-value (:tags row) json/keyword-keys-object-mapper) - :rating {:score (:rating_score row) :count (:rating_count row)}}) - (defn- transform-pg-row [row] {:id (:id row) :name (:name row) @@ -196,10 +183,6 @@ (println (str "Failed to start server on port " port ": " (.getMessage e)))))))) -(defn- init-sqlite [] - (when (.exists (io/file db-path)) - (jdbc/get-datasource {:dbtype "sqlite" :dbname db-path :read-only true}))) - (defn- init-postgres [] (when-let [url (System/getenv "DATABASE_URL")] (try @@ -242,22 +225,10 @@ (with-open [^InputStream in (:body req)] (text-response (.transferTo in (OutputStream/nullOutputStream))))) -(defn- query-sqlite-items [ds params] - (try (mapv transform-sqlite-row (sqlite-query ds params)) - (catch Exception _ []))) - (defn- query-pg-items [ds params] (try (mapv transform-pg-row (pg-query ds params)) (catch Exception _ []))) -(defn- handle-sqlite [ds req] - (let [params (parse-qs (:query-string req)) - min-p (safe-parse-double (get params param-min) 10.0) - max-p (safe-parse-double (get params param-max) 50.0) - limit (safe-parse-long (get params param-limit) 50) - items (query-sqlite-items ds {:min min-p :max max-p :limit limit})] - (json-response {:items items :count (clojure.core/count items)}))) - (defn- handle-pg [ds req] (let [params (parse-qs (:query-string req)) min-p (safe-parse-double (get params param-min) 10.0) @@ -353,13 +324,12 @@ :body f} {:status 404 :body not-found-body}))) -(defn- build-handler [{:keys [dataset sqlite-ds pg-ds]}] +(defn- build-handler [{:keys [dataset pg-ds]}] (route {"/baseline11" [(GET handle-baseline-get) (POST handle-baseline-post)] "/json/:count" [(GET (fn [req] (handle-json dataset req)))] "/upload" [(POST handle-upload)] - "/db" [(GET (fn [req] (handle-sqlite sqlite-ds req)))] "/async-db" [(GET (fn [req] (handle-pg pg-ds req)))] "/crud/items" [(GET (fn [req] (handle-crud-list pg-ds req))) (POST (fn [req] (handle-crud-create pg-ds req)))] @@ -371,7 +341,6 @@ (defn -main [& _] (let [dataset (load-json (or (System/getenv "DATASET_PATH") dataset-path)) handler (build-handler {:dataset dataset - :sqlite-ds (init-sqlite) :pg-ds (init-postgres)})] (start-server! handler plain-port) (start-server! handler tls-port (load-ssl-context)))) \ No newline at end of file