A Clojure library designed to provide hassle-free, ready to go gRPC experience without ton of preparations and Java code...
...or just a bunch of macros.
netty
, what Java class to import where, etc.kebab-case
to camelCase
conversion in some places (weird identifiers might cause
problems here and there)example_id
from request)clj-grpc
without danielsz/system
spec
). But this is just a bunch of macros developed on real project, so I had no time to build
full testing workflow.clj-grpc
currently implements only system
(component
) behavior.lein-protoc
project.clj
add clj-grpc
to dependencies:[clj-grpc "0.1.0"]
lein-protoc
plugin. Please note, that until original protoc
is fixed, for Clojure 1.9 you have to use
awebneck
fork. For more details, see https://github.com/LiaisonTechnologies/lein-protoc/pull/16:plugins [...
[org.clojars.awebneck/lein-protoc "0.5.5"]
...
]
;; decide which version of protoc and grpc-java to use
:protoc-version "3.10.0"
:protoc-grpc {:version "1.25.0"}
:protoc-source-paths ["src/proto"] ;; where to look for `.proto` files
:proto-target-path "target/generated-sources/protobuf" ;; where should protoc put generated sources
:java-source-paths [... "target/generated-sources/protobuf"] ;; point java compiler to newly generated sources
example.proto
file in src/protoc
:syntax = "proto3";
option java_package = "example.grpc_api";
option java_outer_classname = "ExampleProto";
package example;
message GetAllExamplesParams {
}
message GetExampleParams {
string example_id = 1;
}
service Example {
rpc GetExample (GetExampleParams) returns (Example) {
}
rpc GetAllExamples (GetAllExamplesParams) returns (stream Example) {
}
}
message Example {
string example_id = 1;
string name = 2;
string description = 3;
}
grpc
service:(ns example.grpc-api.core
;; require macros from `clj-grpc.server` namespace
(:require [clj-grpc.server :refer [implement-grpc-service defrpc on-next]]))
;; describe service which will be implemented in this namespace.
;; `:java-package` and `:java-outer-classname` has to be consistent with `proto` file
;;
;; NOTE: it might be necessary to restart Clojure process after this is defined so all the classes will be compiled
(implement-grpc-service Client
:java-package "data_engine.grpc.client"
:java-outer-classname "ClientProto" )
;; define RPC method `getExample` returning only one example
(defrpc getManualMeasurement [_this _req res]
;;
;; do some code here
;;
;; Finally call `on-next` which builds message of type `Example`, initializes it with provided map
;; handling kebab-case to camelCase conversion and sends it through StreamObserver `res`
(on-next "Example" res
{:name "Name"
:description "Description"
:example-id "example-123123123"}))
;; Another example of method, this time `server-streaming`.
;; Implemenation has nothing specific about it, just call `on-next` multiple times
(defrpc getManualMeasurements [_this _req res]
(dotimes [x 10]
(on-next "Example" res
{:name (str "Name " x)
:description (str "Description" x)
:example-id (str "example-" x)})))
danielsz/system
, add GrpcServer
component to your system definition:;; Require `new-grpc-server`
(ns example.systems
"System definition"
(:require [com.stuartsierra.component :as component]
[system.core :refer [defsystem]]
[clj-grpc.server :refer [new-grpc-server]]
...
)
;; Add `GrpcServer` to system definition. Specify port on which to listen and services, that is sequence of vectors
;; specifying pairs of:
;; - Clojure namespace, where desired gRPC service is implemented (in our case
(defsystem dev-system
[...
:my-grpc-server (new-grpc-server :port 5000 :services [["data-engine.grpc.client.core" "Client"]])
...
]
Start you system with system's (start)
and you should have your service running!
To avoid warnings and unexpected behaviour when using provided macros, configure their IDE resolution as follows:
implement-grpc-service
- resolve as def
defgrpc
- resolve as defn
Behavior won't be perfect, but good enough - for example warnings about unused functions might still occur.
See https://cursive-ide.com/userguide/macros.html#customising-symbol-resolution for more info.
Copyright © 2019 FIXME
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close