Skip to content

Commit 57c1493

Browse files
Provides grpc configuration DSL and GrpcServer algebras (#13)
* Provides grpc configuration DSL and GrpcServer algebras Server Demo has been also adapated to the new introduced changes, where the rpc core provides helpers in order to bootstrap the server in the runtime monad, according to the server configuration.
1 parent eac2453 commit 57c1493

File tree

14 files changed

+357
-48
lines changed

14 files changed

+357
-48
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ You could generate a reverse proxy and writing an endpoint as it's described [he
9696
To run the gateway:
9797

9898
```bash
99-
go run demo/gateway/server/entry.go
99+
go run demo/http/gateway/server/entry.go
100100
```
101101

102102
Then, you could use `curl` or similar to fetch the user over `HTTP`:

build.sbt

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ lazy val rpc = project
1616
.settings(moduleName := "freestyle-rpc")
1717
.settings(
1818
Seq(
19-
libraryDependencies ++= commonDeps ++ freestyleCoreDeps()
19+
libraryDependencies ++= commonDeps ++ freestyleCoreDeps() ++
20+
Seq(
21+
"io.grpc" % "grpc-all" % "1.4.0"
22+
)
2023
): _*
2124
)
2225

demo/greeting/src/main/scala/greeting/GreetingClientApp.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ object GreetingClientApp {
2222
def main(args: Array[String]): Unit = {
2323

2424
val request = MessageRequest("Freestyle")
25-
val client = new GreetingClient(host, port)
25+
val client = new GreetingClient(host, portNode1)
26+
// val client = new GreetingClient(host, portNode2)
2627

2728
// http://www.grpc.io/docs/guides/concepts.html
2829

demo/greeting/src/main/scala/greeting/GreetingServerApp.scala

+9-11
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,16 @@
1717
package freestyle.rpc.demo
1818
package greeting
1919

20-
import scala.concurrent.ExecutionContext
20+
import cats.implicits._
21+
import freestyle.rpc.server._
22+
import freestyle.rpc.server.implicits._
23+
import runtime.implicits._
2124

22-
object GreetingServerApp {
23-
24-
def main(args: Array[String]): Unit = {
25+
import scala.concurrent.duration.Duration
26+
import scala.concurrent.Await
2527

26-
val serverServiceDefinition =
27-
GreeterGrpc.bindService(new GreetingService, ExecutionContext.global)
28-
val server = new GrpcServer(serverServiceDefinition)
29-
30-
server.start()
31-
server.blockUntilShutdown()
32-
}
28+
object GreetingServerApp {
3329

30+
def main(args: Array[String]): Unit =
31+
Await.result(server[GrpcServer.Op].bootstrapFuture, Duration.Inf)
3432
}

demo/greeting/src/main/scala/GrpcServer.scala renamed to demo/greeting/src/main/scala/greeting/runtime/implicits.scala

+16-19
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,27 @@
1515
*/
1616

1717
package freestyle.rpc.demo
18-
package greeting
18+
package greeting.runtime
1919

20-
import io.grpc.{Server, ServerBuilder, ServerServiceDefinition}
20+
import freestyle._
21+
import freestyle.implicits._
22+
import freestyle.rpc.demo.greeting._
23+
import freestyle.rpc.server._
24+
import freestyle.rpc.server.implicits._
25+
import freestyle.rpc.server.handlers._
2126

22-
class GrpcServer(serverServiceDefinition: ServerServiceDefinition) {
27+
import scala.concurrent.{ExecutionContext, Future}
2328

24-
var server: Option[Server] = None
29+
object implicits {
2530

26-
def start(): Unit = {
27-
server = Option(
28-
ServerBuilder
29-
.forPort(port)
30-
.addService(serverServiceDefinition)
31-
.build
32-
.start
33-
)
31+
implicit val config: Config = Config(portNode1)
32+
implicit val ec: ExecutionContext = ExecutionContext.Implicits.global
3433

35-
Runtime.getRuntime.addShutdownHook(new Thread() {
36-
override def run(): Unit = stopServer()
37-
})
38-
}
34+
implicit val grpcConfigs: List[GrpcConfig] = List(
35+
AddService(GreeterGrpc.bindService(new GreetingService, ec))
36+
)
3937

40-
def stopServer(): Unit = server.foreach(_.shutdown())
38+
implicit val grpcServerHandler =
39+
new GrpcServerHandler[Future] andThen new GrpcConfigInterpreter[Future]
4140

42-
def blockUntilShutdown(): Unit =
43-
server.foreach(_.awaitTermination())
4441
}

demo/greeting/src/main/scala/package.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ package freestyle.rpc
1818

1919
package object demo {
2020

21-
val host = "localhost"
22-
val port = 50051
21+
val host = "localhost"
22+
val portNode1 = 50051
23+
val portNode2 = 50052
2324

2425
}

demo/http/src/main/scala/user/UserClientApp.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ object UserClientApp {
2424

2525
def main(args: Array[String]): Unit = {
2626
val request = UserPassword("frees", "password")
27-
val client = new UserClient(host, port)
27+
val client = new UserClient(host, portNode1)
2828

2929
val response = client.login(request)
3030

demo/http/src/main/scala/user/UserServerApp.scala

+8-12
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,16 @@
1717
package freestyle.rpc.demo
1818
package user
1919

20-
import freestyle.rpc.demo.greeting.GrpcServer
20+
import cats.implicits._
21+
import freestyle.rpc.server._
22+
import freestyle.rpc.server.implicits._
23+
import runtime.implicits._
2124

22-
import scala.concurrent.ExecutionContext
25+
import scala.concurrent.duration.Duration
26+
import scala.concurrent.Await
2327

2428
object UserServerApp {
2529

26-
def main(args: Array[String]): Unit = {
27-
28-
val serverServiceDefinition =
29-
UserServiceGrpc.bindService(new UserService, ExecutionContext.global)
30-
val server = new GrpcServer(serverServiceDefinition)
31-
32-
server.start()
33-
server.blockUntilShutdown()
34-
}
35-
30+
def main(args: Array[String]): Unit =
31+
Await.result(server[GrpcServer.Op].bootstrapFuture, Duration.Inf)
3632
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2017 47 Degrees, LLC. <http://www.47deg.com>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package freestyle.rpc.demo
18+
package user.runtime
19+
20+
import freestyle._
21+
import freestyle.implicits._
22+
import freestyle.rpc.demo.user._
23+
import freestyle.rpc.server._
24+
import freestyle.rpc.server.implicits._
25+
import freestyle.rpc.server.handlers._
26+
27+
import scala.concurrent.{ExecutionContext, Future}
28+
29+
object implicits {
30+
31+
implicit val config: Config = Config(portNode1)
32+
implicit val ec: ExecutionContext = ExecutionContext.Implicits.global
33+
34+
implicit val grpcConfigs: List[GrpcConfig] = List(
35+
AddService(UserServiceGrpc.bindService(new UserService, ExecutionContext.global))
36+
)
37+
38+
implicit val grpcServerHandler =
39+
new GrpcServerHandler[Future] andThen new GrpcConfigInterpreter[Future]
40+
41+
}
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2017 47 Degrees, LLC. <http://www.47deg.com>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package freestyle.rpc
18+
package server
19+
20+
import java.io.File
21+
import java.util.concurrent.Executor
22+
23+
import io.grpc._
24+
25+
case class Config(port: Int)
26+
27+
sealed trait GrpcConfig extends Product with Serializable
28+
29+
case object DirectExecutor extends GrpcConfig
30+
31+
case class SetExecutor(executor: Executor) extends GrpcConfig
32+
33+
case class AddService(service: ServerServiceDefinition) extends GrpcConfig
34+
35+
case class AddBindableService(bindableService: BindableService) extends GrpcConfig
36+
37+
case class AddTransportFilter(filter: ServerTransportFilter) extends GrpcConfig
38+
39+
case class AddStreamTracerFactory(factory: ServerStreamTracer.Factory) extends GrpcConfig
40+
41+
case class SetFallbackHandlerRegistry(fallbackRegistry: HandlerRegistry) extends GrpcConfig
42+
43+
case class UseTransportSecurity(certChain: File, privateKey: File) extends GrpcConfig
44+
45+
case class SetDecompressorRegistry(registry: DecompressorRegistry) extends GrpcConfig
46+
47+
case class SetCompressorRegistry(registry: CompressorRegistry) extends GrpcConfig
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2017 47 Degrees, LLC. <http://www.47deg.com>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package freestyle.rpc
18+
package server
19+
20+
import freestyle._
21+
import io.grpc._
22+
23+
import scala.concurrent.duration.TimeUnit
24+
25+
@free
26+
trait GrpcServer {
27+
28+
def start(): FS[Server]
29+
30+
def getPort: FS[Int]
31+
32+
def getServices: FS[List[ServerServiceDefinition]]
33+
34+
def getImmutableServices: FS[List[ServerServiceDefinition]]
35+
36+
def getMutableServices: FS[List[ServerServiceDefinition]]
37+
38+
def shutdown(): FS[Server]
39+
40+
def shutdownNow(): FS[Server]
41+
42+
def isShutdown: FS[Boolean]
43+
44+
def isTerminated: FS[Boolean]
45+
46+
def awaitTerminationTimeout(timeout: Long, unit: TimeUnit): FS[Boolean]
47+
48+
def awaitTermination(): FS[Unit]
49+
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2017 47 Degrees, LLC. <http://www.47deg.com>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package freestyle.rpc
18+
package server.handlers
19+
20+
import cats.data.Kleisli
21+
import freestyle.rpc.server.{GrpcServer, GrpcServerOps}
22+
import freestyle.Capture
23+
import io.grpc.{Server, ServerServiceDefinition}
24+
25+
import scala.collection.JavaConverters._
26+
import scala.concurrent.duration.TimeUnit
27+
28+
class GrpcServerHandler[F[_]](implicit C: Capture[F])
29+
extends GrpcServer.Handler[GrpcServerOps[F, ?]] {
30+
31+
def start: GrpcServerOps[F, Server] = {
32+
33+
Runtime.getRuntime.addShutdownHook(new Thread() {
34+
override def run(): Unit = {
35+
shutdown
36+
(): Unit
37+
}
38+
})
39+
40+
captureWithServer(_.start())
41+
}
42+
43+
def getPort: GrpcServerOps[F, Int] = captureWithServer(_.getPort)
44+
45+
def getServices: GrpcServerOps[F, List[ServerServiceDefinition]] =
46+
captureWithServer(_.getServices.asScala.toList)
47+
48+
def getImmutableServices: GrpcServerOps[F, List[ServerServiceDefinition]] =
49+
captureWithServer(_.getImmutableServices.asScala.toList)
50+
51+
def getMutableServices: GrpcServerOps[F, List[ServerServiceDefinition]] =
52+
captureWithServer(_.getMutableServices.asScala.toList)
53+
54+
def shutdown: GrpcServerOps[F, Server] = captureWithServer(_.shutdown())
55+
56+
def shutdownNow: GrpcServerOps[F, Server] = captureWithServer(_.shutdownNow())
57+
58+
def isShutdown: GrpcServerOps[F, Boolean] = captureWithServer(_.isShutdown)
59+
60+
def isTerminated: GrpcServerOps[F, Boolean] = captureWithServer(_.isTerminated)
61+
62+
def awaitTerminationTimeout(timeout: Long, unit: TimeUnit): GrpcServerOps[F, Boolean] =
63+
captureWithServer(_.awaitTermination(timeout, unit))
64+
65+
def awaitTermination: GrpcServerOps[F, Unit] = captureWithServer(_.awaitTermination())
66+
67+
private[this] def captureWithServer[A](f: Server => A): GrpcServerOps[F, A] =
68+
Kleisli(s => C.capture(f(s)))
69+
70+
}

0 commit comments

Comments
 (0)