diff --git a/.github/workflows/clojure.yml b/.github/workflows/clojure.yml index f313616..517f815 100644 --- a/.github/workflows/clojure.yml +++ b/.github/workflows/clojure.yml @@ -17,3 +17,15 @@ jobs: run: lein deps - name: Run tests run: lein test + + formatter: + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Install dependencies + run: lein deps + - name: Run cljfmt + run: lein cljfmt check + - name: Run kibit + run: lein kibit \ No newline at end of file diff --git a/.gitignore b/.gitignore index dcf77d1..c716865 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ pom.xml.asc .lsp/ .clj-kondo/ .calva/ +.eastwood \ No newline at end of file diff --git a/README.md b/README.md index ddf1f03..ccb5894 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,18 @@ gRPC Plugin for XTDB +## Usage: + +1. Install [leiningen](https://leiningen.org/) +2. execute `make all` after making changes to the `*.proto` files in `resources/` + +* Execute server: `lein run` +* Run tests: `lein test` +* Format code, Check: `lein cljfmt check`, Fix: `lein cljfmt fix` +* Lint code, Check: `lein kibit`, Fix: `lein kibit --replace` + + +# Protojure stuff ## Usage This is the output of a `lein new protojure` template run. The output is a set of sample files demonstrating the use of the protojure lib + protoc plugin to expose a GRPC service. diff --git a/project.clj b/project.clj index ba9d02c..6ccf7b1 100644 --- a/project.clj +++ b/project.clj @@ -5,7 +5,9 @@ :url "https://www.mit.edu/~amini/LICENSE.md" :year 2023 :key "mit"} - :plugins [[lein-cljfmt "0.9.2"]] + :plugins [[lein-cljfmt "0.9.2"] + [lein-kibit "0.1.8"] + [jonase/eastwood "1.4.0"]] :dependencies [[org.clojure/clojure "1.10.3"] [com.xtdb/xtdb-core "1.22.1"] [io.pedestal/pedestal.service "0.5.9"] diff --git a/src/com/xtdb/protos.cljc b/src/com/xtdb/protos.cljc index fb9a625..04a01eb 100644 --- a/src/com/xtdb/protos.cljc +++ b/src/com/xtdb/protos.cljc @@ -36,20 +36,18 @@ (defn convert-OptionString-value [origkeyval] (cond - (get-in origkeyval [:value :none]) (update-in origkeyval [:value :none] new-Empty) - (get-in origkeyval [:value :some]) origkeyval - :default origkeyval)) + (get-in origkeyval [:value :none]) (update-in origkeyval [:value :none] new-Empty) + (get-in origkeyval [:value :some]) origkeyval + :default origkeyval)) (defn write-OptionString-value [value os] (let [field (first value) k (when-not (nil? field) (key field)) v (when-not (nil? field) (val field))] - (case k - :none (serdes.core/write-embedded 1 v os) - :some (serdes.core/write-String 2 {:optimize false} v os) - nil))) - - + (case k + :none (serdes.core/write-embedded 1 v os) + :some (serdes.core/write-String 2 {:optimize false} v os) + nil))) ;;---------------------------------------------------------------------------------- ;;---------------------------------------------------------------------------------- @@ -62,8 +60,7 @@ ;----------------------------------------------------------------------------- (defrecord Empty-record [] pb/Writer - (serialize [this os] -) + (serialize [this os]) pb/TypeReflection (gettype [this] "com.xtdb.protos.Empty")) @@ -74,12 +71,7 @@ (defn cis->Empty "CodedInputStream to Empty" [is] - (->> (tag-map Empty-defaults - (fn [tag index] - (case index - [index (serdes.core/cis->undefined tag is)])) - is) - (map->Empty-record))) + (map->Empty-record (tag-map Empty-defaults (fn [tag index] (case index [index (serdes.core/cis->undefined tag is)])) is))) (defn ecis->Empty "Embedded CodedInputStream to Empty" @@ -92,8 +84,7 @@ " [init] {:pre [(if (s/valid? ::Empty-spec init) true (throw (ex-info "Invalid input" (s/explain-data ::Empty-spec init))))]} - (-> (merge Empty-defaults init) - (map->Empty-record))) + (map->Empty-record (merge Empty-defaults init))) (defn pb->Empty "Protobuf to Empty" @@ -119,15 +110,7 @@ (defn cis->OptionString "CodedInputStream to OptionString" [is] - (->> (tag-map OptionString-defaults - (fn [tag index] - (case index - 1 [:value {:none (ecis->Empty is)}] - 2 [:value {:some (serdes.core/cis->String is)}] - - [index (serdes.core/cis->undefined tag is)])) - is) - (map->OptionString-record))) + (map->OptionString-record (tag-map OptionString-defaults (fn [tag index] (case index 1 [:value {:none (ecis->Empty is)}] 2 [:value {:some (serdes.core/cis->String is)}] [index (serdes.core/cis->undefined tag is)])) is))) (defn ecis->OptionString "Embedded CodedInputStream to OptionString" @@ -174,27 +157,13 @@ (s/def :com.xtdb.protos.StatusResponse/estimate-num-keys int?) (s/def :com.xtdb.protos.StatusResponse/size int?) - -(s/def ::StatusResponse-spec (s/keys :opt-un [:com.xtdb.protos.StatusResponse/version :com.xtdb.protos.StatusResponse/index-version :com.xtdb.protos.StatusResponse/kv-store :com.xtdb.protos.StatusResponse/estimate-num-keys :com.xtdb.protos.StatusResponse/size ])) -(def StatusResponse-defaults {:version "" :index-version 0 :kv-store "" :estimate-num-keys 0 :size 0 }) +(s/def ::StatusResponse-spec (s/keys :opt-un [:com.xtdb.protos.StatusResponse/version :com.xtdb.protos.StatusResponse/index-version :com.xtdb.protos.StatusResponse/kv-store :com.xtdb.protos.StatusResponse/estimate-num-keys :com.xtdb.protos.StatusResponse/size])) +(def StatusResponse-defaults {:version "" :index-version 0 :kv-store "" :estimate-num-keys 0 :size 0}) (defn cis->StatusResponse "CodedInputStream to StatusResponse" [is] - (->> (tag-map StatusResponse-defaults - (fn [tag index] - (case index - 1 [:version (serdes.core/cis->String is)] - 2 [:index-version (serdes.core/cis->Int32 is)] - 3 [:kv-store (serdes.core/cis->String is)] - 4 [:estimate-num-keys (serdes.core/cis->Int32 is)] - 5 [:size (serdes.core/cis->Int64 is)] - 6 [:revision (ecis->OptionString is)] - 7 [:consumer-state (ecis->OptionString is)] - - [index (serdes.core/cis->undefined tag is)])) - is) - (map->StatusResponse-record))) + (map->StatusResponse-record (tag-map StatusResponse-defaults (fn [tag index] (case index 1 [:version (serdes.core/cis->String is)] 2 [:index-version (serdes.core/cis->Int32 is)] 3 [:kv-store (serdes.core/cis->String is)] 4 [:estimate-num-keys (serdes.core/cis->Int32 is)] 5 [:size (serdes.core/cis->Int64 is)] 6 [:revision (ecis->OptionString is)] 7 [:consumer-state (ecis->OptionString is)] [index (serdes.core/cis->undefined tag is)])) is))) (defn ecis->StatusResponse "Embedded CodedInputStream to StatusResponse" diff --git a/src/com/xtdb/protos/GrpcApi/client.cljc b/src/com/xtdb/protos/GrpcApi/client.cljc index 2df09e3..3880ac7 100644 --- a/src/com/xtdb/protos/GrpcApi/client.cljc +++ b/src/com/xtdb/protos/GrpcApi/client.cljc @@ -19,13 +19,12 @@ (defn Status ([client params] (Status client {} params)) ([client metadata params] - (let [input (async/chan 1) - output (async/chan 1) - desc {:service "com.xtdb.protos.GrpcApi" - :method "Status" - :input {:f com.xtdb.protos/new-Empty :ch input} - :output {:f com.xtdb.protos/pb->StatusResponse :ch output} - :metadata metadata}] - (-> (send-unary-params input params) - (p/then (fn [_] (invoke-unary client desc output))))))) + (let [input (async/chan 1) + output (async/chan 1) + desc {:service "com.xtdb.protos.GrpcApi" + :method "Status" + :input {:f com.xtdb.protos/new-Empty :ch input} + :output {:f com.xtdb.protos/pb->StatusResponse :ch output} + :metadata metadata}] + (p/then (send-unary-params input params) (fn [_] (invoke-unary client desc output)))))) diff --git a/src/com/xtdb/protos/GrpcApi/server.cljc b/src/com/xtdb/protos/GrpcApi/server.cljc index 46c72f6..a56d271 100644 --- a/src/com/xtdb/protos/GrpcApi/server.cljc +++ b/src/com/xtdb/protos/GrpcApi/server.cljc @@ -4,8 +4,7 @@ ;;; GRPC com.xtdb.protos.GrpcApi Service Implementation ;;;---------------------------------------------------------------------------------- (ns com.xtdb.protos.GrpcApi.server - (:require [com.xtdb.protos :refer :all] -)) + (:require [com.xtdb.protos :refer :all])) ;----------------------------------------------------------------------------- ; GRPC GrpcApi diff --git a/src/gxtdb/adapters/status.clj b/src/gxtdb/adapters/status.clj index d00b116..6d94067 100644 --- a/src/gxtdb/adapters/status.clj +++ b/src/gxtdb/adapters/status.clj @@ -1,5 +1,5 @@ (ns gxtdb.adapters.status - (:require [gxtdb.utils :as utils])) + (:require [gxtdb.utils :as utils])) (defn edn->grpc [edn] (-> diff --git a/src/gxtdb/server.clj b/src/gxtdb/server.clj index ddb7d50..2dd90cf 100644 --- a/src/gxtdb/server.clj +++ b/src/gxtdb/server.clj @@ -6,7 +6,7 @@ ;; This is an adapted service map, that can be started and stopped ;; From the REPL you can call server/start and server/stop on this service -(defn runnable-service [xtdb-node] (-> xtdb-node service/service server/create-server )) +(defn runnable-service [xtdb-node] (-> xtdb-node service/service server/create-server)) (defn -run-test "The entry-point for 'lein run-dev'" diff --git a/src/gxtdb/service.clj b/src/gxtdb/service.clj index 0eef458..235155c 100644 --- a/src/gxtdb/service.clj +++ b/src/gxtdb/service.clj @@ -3,7 +3,7 @@ [io.pedestal.http.route :as route] [io.pedestal.http.body-params :as body-params] [ring.util.response :as ring-resp] - + [gxtdb.adapters.status :as status-adapter] ;; -- XTDB -- @@ -39,7 +39,6 @@ ;; ;; see http://pedestal.io/reference/request-map - (defonce xtdb-in-memory-node (xt/start-node {})) (deftype GrpcAPI [xtdb-node] @@ -61,11 +60,11 @@ ;; -- PROTOC-GEN-CLOJURE -- ;; Add the routes produced by Greeter->routes -(defn grpc-routes [xtdb-node] (reduce conj routes (proutes/->tablesyntax {:rpc-metadata api/rpc-metadata :interceptors common-interceptors :callback-context (GrpcAPI. xtdb-node) }))) +(defn grpc-routes [xtdb-node] (reduce conj routes (proutes/->tablesyntax {:rpc-metadata api/rpc-metadata :interceptors common-interceptors :callback-context (GrpcAPI. xtdb-node)}))) -(defn service [xtdb-node] - {:env :prod - ::http/routes (grpc-routes xtdb-node) +(defn service [xtdb-node] + {:env :prod + ::http/routes (grpc-routes xtdb-node) ;; -- PROTOC-GEN-CLOJURE -- ;; We override the chain-provider with one provided by protojure.protobuf @@ -73,8 +72,8 @@ ;; for HTTP/2 trailers, which GRPCs rely on. A future version of pedestal ;; may provide this support, in which case we can go back to using ;; chain-providers from pedestal. - ::http/type protojure.pedestal/config - ::http/chain-provider protojure.pedestal/provider + ::http/type protojure.pedestal/config + ::http/chain-provider protojure.pedestal/provider ;;::http/host "localhost" - ::http/port 8080}) + ::http/port 8080}) diff --git a/src/gxtdb/utils.clj b/src/gxtdb/utils.clj index 3e69298..7cf57ea 100644 --- a/src/gxtdb/utils.clj +++ b/src/gxtdb/utils.clj @@ -1,5 +1,5 @@ (ns gxtdb.utils - (:require [clojure.instant :refer [read-instant-date]] + (:require [clojure.instant :refer [read-instant-date]] [clojure.string :as str]) (:import java.text.SimpleDateFormat)) diff --git a/test/gxtdb/service_test.clj b/test/gxtdb/service_test.clj index 365be01..b137adb 100644 --- a/test/gxtdb/service_test.clj +++ b/test/gxtdb/service_test.clj @@ -12,7 +12,6 @@ (def xtdb-server (service/grpc-routes (xt/start-node *opts*))) - (def test-env (atom {})) (defn create-service [] @@ -39,7 +38,7 @@ (use-fixtures :each wrap-service) (deftest status-test (testing "Status return xtdb with MemKv" - (is (= - (:kv-store @(Status @(connect {:uri (str "http://localhost:" (:port @test-env))}) {})) - "xtdb.mem_kv.MemKv")))) + (is (= + (:kv-store @(Status @(connect {:uri (str "http://localhost:" (:port @test-env))}) {})) + "xtdb.mem_kv.MemKv"))))