ProductPromotion
Logo

Clojure

made by https://0x3d.site

GitHub - otwieracz/clj-grpc: A Clojure library designed to provide hassle-free, ready to go gRPC experience without ton of preparations and Java code.
A Clojure library designed to provide hassle-free, ready to go gRPC experience without ton of preparations and Java code. - otwieracz/clj-grpc
Visit Site

GitHub - otwieracz/clj-grpc: A Clojure library designed to provide hassle-free, ready to go gRPC experience without ton of preparations and Java code.

GitHub - otwieracz/clj-grpc: A Clojure library designed to provide hassle-free, ready to go gRPC experience without ton of preparations and Java code.

clj-grpc

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 functions and macros.

Rationale

  • Enable easy and fast integration of gRPC into existing projects
  • Save user from painful Java-in-Clojure experience
  • Only require user to read basic Java tutorial for gRPC (https://grpc.io/docs/tutorials/basic/java/) without necessarily taking deep dive into all the Java libraries around gRPC, servers like netty, what Java class to import where, etc.
  • Avoid creating new logic, letting user to follow official Java guide.

Assumptions

  • One gRPC service is implemented per Clojure namespace
  • Maybe being too optimistic about kebab-case to camelCase conversion in some places (weird identifiers might cause problems here and there)

TODO

  • Client-streaming methods
  • Tests - unfortunately, there are none (only thin layer of spec). But this is just a bunch of macros developed on real project, so I had no time to build full testing workflow.

See also (or rather "read before use")

Credits

Usage

  • In project.clj add clj-grpc to dependencies:
[clj-grpc "0.1.0"]
: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
  • Create 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;
}
  • Create namespace implementing 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 getExample [_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-id req)}))

;; Another example of method, this time `server-streaming`.
;; Implemenation has nothing specific about it, just call `on-next` multiple times

(defrpc getAllExamples [_this _req res]
  (dotimes [x 10]
    (on-next "Example" res
           {:name                  (str "Name " x)
            :description           (str "Description" x)
            :example-id            (str "example-" x)})))
  • Assuming you're using 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. It will automatically server 
;; all services defined with `IMPLEMENT-GRPC-SERVICE`
(defsystem dev-system
           [...
            :my-grpc-server (new-grpc-server :port 5000)
            ...
            ]
  • Otherwise, just call (start-grpc (make-grpc-server :port <port-number>))from clj-grpc.server and you should be up and running.

Start you system with system's (start) and you should have your service running!

Note for IntelliJ IDEA + Cursive users

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.

License

Copyright © 2019 Slawomir Gonet [email protected]

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

More Resources
to explore the angular.

mail [email protected] to add your project or resources here 🔥.

Related Articles
to learn about angular.

FAQ's
to learn more about Angular JS.

mail [email protected] to add more queries here 🔍.

More Sites
to check out once you're finished browsing here.

0x3d
https://www.0x3d.site/
0x3d is designed for aggregating information.
NodeJS
https://nodejs.0x3d.site/
NodeJS Online Directory
Cross Platform
https://cross-platform.0x3d.site/
Cross Platform Online Directory
Open Source
https://open-source.0x3d.site/
Open Source Online Directory
Analytics
https://analytics.0x3d.site/
Analytics Online Directory
JavaScript
https://javascript.0x3d.site/
JavaScript Online Directory
GoLang
https://golang.0x3d.site/
GoLang Online Directory
Python
https://python.0x3d.site/
Python Online Directory
Swift
https://swift.0x3d.site/
Swift Online Directory
Rust
https://rust.0x3d.site/
Rust Online Directory
Scala
https://scala.0x3d.site/
Scala Online Directory
Ruby
https://ruby.0x3d.site/
Ruby Online Directory
Clojure
https://clojure.0x3d.site/
Clojure Online Directory
Elixir
https://elixir.0x3d.site/
Elixir Online Directory
Elm
https://elm.0x3d.site/
Elm Online Directory
Lua
https://lua.0x3d.site/
Lua Online Directory
C Programming
https://c-programming.0x3d.site/
C Programming Online Directory
C++ Programming
https://cpp-programming.0x3d.site/
C++ Programming Online Directory
R Programming
https://r-programming.0x3d.site/
R Programming Online Directory
Perl
https://perl.0x3d.site/
Perl Online Directory
Java
https://java.0x3d.site/
Java Online Directory
Kotlin
https://kotlin.0x3d.site/
Kotlin Online Directory
PHP
https://php.0x3d.site/
PHP Online Directory
React JS
https://react.0x3d.site/
React JS Online Directory
Angular
https://angular.0x3d.site/
Angular JS Online Directory