-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
589 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
*.class | ||
*.log | ||
target/ | ||
*/target/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
dist: trusty | ||
language: scala | ||
jdk: openjdk8 | ||
|
||
script: | ||
- sbt ++2.10.6 generator/compile | ||
- sbt ++2.12.2 runtime/compile | ||
- test $TRAVIS_PULL_REQUEST = false && sbt updateImpactSubmit || true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,116 @@ | ||
# grpcmonix | ||
Use Monix's Observable with GRPC services | ||
[![Build status](https://api.travis-ci.org/btlines/grpcmonix.svg?branch=master)](https://travis-ci.org/btlines/grpcmonix) | ||
[![Dependencies](https://app.updateimpact.com/badge/852442212779298816/grpcmonix.svg?config=compile)](https://app.updateimpact.com/latest/852442212779298816/grpcmonix) | ||
[![License](https://img.shields.io/:license-MIT-blue.svg)](https://opensource.org/licenses/MIT) | ||
[![GRPCMonixGenerator](https://api.bintray.com/packages/beyondthelines/maven/grpcmonixgenerator/images/download.svg) ](https://bintray.com/beyondthelines/maven/grpcmonixgenerator/_latestVersion) | ||
[![GRPCMonixRuntime](https://api.bintray.com/packages/beyondthelines/maven/grpcmonixruntime/images/download.svg) ](https://bintray.com/beyondthelines/maven/grpcmonixruntime/_latestVersion) | ||
|
||
# GRPC Monix | ||
|
||
Use Monix's Tasks and Observables to implement your GRPC services instead of Java's StreamObservers. | ||
|
||
- Unary calls return a Task[T] for the response returned by the server | ||
- Server streaming calls return an Observable[T] for the elements returned by the server | ||
- Client streaming calls take an Observable[T] for the elements emitted by the client and return a Task[U] for the server response | ||
- Bidi streaming calls take an Observable[T] for the elements emitted by the client and return an Observable[U] for the elements returned by the server | ||
|
||
## Installation | ||
|
||
You need to enable [`sbt-protoc`](https://github.com/thesamet/sbt-protoc) plugin to generate source code for the proto definitions. | ||
You can do it by adding a `protoc.sbt` file into your `project` folder with the following lines: | ||
|
||
```scala | ||
addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.9") | ||
|
||
resolvers += Resolver.bintrayRepo("beyondthelines", "maven") | ||
|
||
libraryDependencies ++= Seq( | ||
"com.trueaccord.scalapb" %% "compilerplugin" % "0.6.0-pre5", | ||
"beyondthelines" %% "grpcmonixgenerator" % "0.0.0" | ||
) | ||
``` | ||
|
||
Here we add a dependency to the GRPCMonix protobuf generator. | ||
|
||
Then we need to trigger the generation from the `build.sbt`: | ||
|
||
```scala | ||
PB.targets in Compile := Seq( | ||
// compile your proto files into scala source files | ||
scalapb.gen() -> (sourceManaged in Compile).value, | ||
// generate the GRPCMonix source code | ||
grpcmonix.generators.GrpcMonixGenerator -> (sourceManaged in Compile).value | ||
) | ||
|
||
resolvers += Resolver.bintrayRepo("beyondthelines", "maven") | ||
|
||
libraryDependencies += "beyondthelines" %% "grpcgatewayruntime" % "0.0.0" | ||
``` | ||
|
||
### Usage | ||
|
||
You're now ready to implement your GRPC service using Monix's Tasks and Observable. | ||
|
||
To implement your service's business logic you simply extend the GRPC monix generated trait. | ||
|
||
E.g. for the RouteGuide service: | ||
|
||
```scala | ||
class RouteGuideMonixService(features: Seq[Feature]) extends RouteGuideGrpcMonix.RouteGuide { | ||
// Unary call | ||
override def getFeature(request: Point): Task[Feature] = ??? | ||
// Server streaming | ||
override def listFeatures(request: Rectangle): Observable[Feature] = ??? | ||
// Client streaming | ||
override def recordRoute(points: Observable[Point]): Task[RouteSummary] = ??? | ||
// Bidi streaming | ||
override def routeChat(notes: Observable[RouteNote]): Observable[RouteNote] = ??? | ||
} | ||
``` | ||
|
||
The server creation is similar except you need to provide a Monix's `Scheduler` instead of an `ExecutionContext` when binding the service | ||
|
||
```scala | ||
val server = ServerBuilder | ||
.forPort(8980) | ||
.addService( | ||
RouteGuideGrpcMonix.bindService( | ||
new RouteGuideMonixService(features), // the service implemented above | ||
monix.execution.Scheduler.global | ||
) | ||
) | ||
.build() | ||
``` | ||
|
||
Tasks and Observables are also available on the client side: | ||
|
||
```scala | ||
val channel = ManagedChannelBuilder | ||
.forAddress("localhost", 8980) | ||
.usePlainText(true) | ||
.build() | ||
|
||
val stub = RouteGuideGrpcMonix.stub(channel) // only an async stub is provided | ||
|
||
// Unary call | ||
val feature: Task[Feature] = stub.getFeature(408031728, -748645385) | ||
// Server streaming | ||
val request = Rectangle( | ||
lo = Some(Point(408031728, -748645385)), | ||
hi = Some(Point(413700272, -742135189)) | ||
) | ||
val features: Observable[Feature] = stub.listFeatures(request) | ||
// Client streaming | ||
val route: Observable[Feature] = Observable | ||
.fromIterable(features.map(_.getLocation)) | ||
.delayOnNext(100.millis) | ||
val summary: Task[RouteSummary] = stub.recordRoute(route) | ||
// Bidi streaming | ||
val notes: Observable[RouteNote] = Observable( | ||
RouteNote(message = "First message", location = Some(Point(0, 0))), | ||
RouteNote(message = "Second message", location = Some(Point(0, 1))), | ||
RouteNote(message = "Third message", location = Some(Point(1, 0))), | ||
RouteNote(message = "Fourth message", location = Some(Point(1, 1))) | ||
).delayOnNext(1.second) | ||
val allNotes = stub.routeChat(notes) | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
lazy val commonSettings = Seq( | ||
organization := "beyondthelines", | ||
version := "0.0.0", | ||
licenses := ("MIT", url("http://opensource.org/licenses/MIT")) :: Nil, | ||
bintrayOrganization := Some("beyondthelines"), | ||
bintrayPackageLabels := Seq("scala", "protobuf", "grpc", "monix") | ||
) | ||
|
||
lazy val runtime = (project in file("runtime")) | ||
.settings( | ||
commonSettings, | ||
scalaVersion := "2.12.2", | ||
crossScalaVersions := Seq("2.12.2", "2.11.11"), | ||
name := "GrpcMonixRuntime", | ||
libraryDependencies ++= Seq( | ||
"com.trueaccord.scalapb" %% "scalapb-runtime-grpc" % "0.6.0-pre5", | ||
"io.monix" %% "monix" % "2.3.0" | ||
) | ||
) | ||
|
||
lazy val generator = (project in file("generator")) | ||
.settings( | ||
commonSettings, | ||
scalaVersion := "2.10.6", | ||
name := "GrpcMonixGenerator", | ||
libraryDependencies ++= Seq( | ||
"com.trueaccord.scalapb" %% "compilerplugin" % "0.6.0-pre5" | ||
) | ||
) |
Oops, something went wrong.