diff --git a/README.md b/README.md index 44cdbb8ec..fa6ca4b3c 100644 --- a/README.md +++ b/README.md @@ -15,28 +15,41 @@ Also known as [frees-rpc], it brings the ability to combine [RPC] protocols, ser `frees-rpc` is cross-built for Scala `2.11.x` and `2.12.x`: -Add the following dependency to your project's build file. - [comment]: # (Start Replace) ```scala -libraryDependencies += "io.frees" %% "frees-rpc-core" % "0.6.1" +// required for the RPC Server: +libraryDependencies += "io.frees" %% "frees-rpc-server" % "0.6.1" + +// required for the RPC Client/s, using either Netty or OkHttp as transport layer: +libraryDependencies += "io.frees" %% "frees-rpc-client-netty" % "0.6.1" +// or: +libraryDependencies += "io.frees" %% "frees-rpc-client-okhttp" % "0.6.1" + +// optional - for both server and client configuration. +libraryDependencies += "io.frees" %% "frees-rpc-config" % "0.6.1" ``` [comment]: # (End Replace) -Optionally, [frees-rpc] provides some configuration helpers using [frees-config] to load the application configuration values. +Note: `frees-rpc-config` provides some configuration helpers using [frees-config] to load the application configuration values. -[comment]: # (Start Replace) +## Documentation -```scala -libraryDependencies += "io.frees" %% "frees-rpc-config" % "0.6.1" -``` +The full documentation is available at [frees-rpc](http://frees.io/docs/rpc) site. -[comment]: # (End Replace) +## Sbt Modules +`frees-rpc` code is placed in different sbt modules: -The full documentation is available at [frees-rpc](http://frees.io/docs/rpc) site. +* `frees-rpc-common`: contains the protocol types, with the minimum set of dependencies. +* `frees-rpc-async`: contains just the async implicit instances (NTs between effect/async types). +* `frees-rpc-internal` where the macros are placed. +* `frees-rpc-client-core`: algebra and code related to the RPC clients. +* `frees-rpc-client-netty`: it doesn't add any additional code, just a transport layer provider based on `grpc-netty`. +* `frees-rpc-client-okhttp`: similar to the `Netty` one, it doesn't add any additional code, just a transport layer provider based on `grpc-okhttp`. +* `frees-rpc-server`: algebra and code related to the RPC server. +* `frees-rpc-config`: helpers to be able to load the client and the server configuration. ## Demo diff --git a/build.sbt b/build.sbt index 7033ae9a8..83c152b0e 100644 --- a/build.sbt +++ b/build.sbt @@ -7,15 +7,52 @@ lazy val common = project .settings(moduleName := "frees-rpc-common") .settings(commonSettings) -lazy val core = project - .in(file("modules/core")) - .dependsOn(common) - .settings(moduleName := "frees-rpc-core") - .settings(coreSettings) +lazy val async = project + .in(file("modules/async")) + .dependsOn(common % "test->test") + .settings(moduleName := "frees-rpc-async") + .settings(asyncSettings) + +lazy val internal = project + .in(file("modules/internal")) + .dependsOn(common % "compile->compile;test->test") + .settings(moduleName := "frees-rpc-internal") + .settings(internalSettings) + +lazy val client = project + .in(file("modules/client")) + .dependsOn(common % "compile->compile;test->test") + .dependsOn(internal) + .dependsOn(async) + .settings(moduleName := "frees-rpc-client-core") + .settings(clientCoreSettings) + +lazy val `client-netty` = project + .in(file("modules/client-netty")) + .dependsOn(client % "compile->compile;test->test") + .settings(moduleName := "frees-rpc-client-netty") + .settings(clientNettySettings) + +lazy val `client-okhttp` = project + .in(file("modules/client-okhttp")) + .dependsOn(client % "compile->compile;test->test") + .settings(moduleName := "frees-rpc-client-okhttp") + .settings(clientOkHttpSettings) + +lazy val server = project + .in(file("modules/server")) + .dependsOn(common % "compile->compile;test->test") + .dependsOn(client % "test->test") + .dependsOn(internal) + .dependsOn(async) + .settings(moduleName := "frees-rpc-server") + .settings(serverSettings) lazy val config = project .in(file("modules/config")) - .dependsOn(core % "compile->compile;test->test") + .dependsOn(common % "test->test") + .dependsOn(client % "compile->compile;test->test") + .dependsOn(server % "compile->compile;test->test") .settings(moduleName := "frees-rpc-config") .settings(configSettings) @@ -25,7 +62,12 @@ lazy val config = project lazy val allModules: Seq[ProjectReference] = Seq( common, - core, + async, + internal, + client, + `client-netty`, + `client-okhttp`, + server, config ) diff --git a/docs/src/main/tut/README.md b/docs/src/main/tut/README.md index 77c56cd11..d1e8257dc 100644 --- a/docs/src/main/tut/README.md +++ b/docs/src/main/tut/README.md @@ -51,26 +51,25 @@ Freestyle RPC is a purely functional library for building RPC endpoint based ser `frees-rpc` is cross-built for Scala `2.11.x` and `2.12.x`: -Add the following dependency to your project's build file. - [comment]: # (Start Replace) ```scala -libraryDependencies += "io.frees" %% "frees-rpc-core" % "0.6.1" -``` - -[comment]: # (End Replace) - -Optionally, [frees-rpc] provides some configuration helpers using [frees-config] to load the application configuration values. +// required for the RPC Server: +libraryDependencies += "io.frees" %% "frees-rpc-server" % "0.6.1" -[comment]: # (Start Replace) +// required for the RPC Client/s, using either Netty or OkHttp as transport layer: +libraryDependencies += "io.frees" %% "frees-rpc-client-netty" % "0.6.1" +// or: +libraryDependencies += "io.frees" %% "frees-rpc-client-okhttp" % "0.6.1" -```scala -libraryDependencies += "io.frees" %% "frees-rpc-config" % "0.6.1" +// optional - for both server and client configuration. +libraryDependencies += "io.frees" %% "frees-rpc-config" % "0.6.1" ``` [comment]: # (End Replace) +Note: `frees-rpc-config` provides some configuration helpers using [frees-config] to load the application configuration values. + ## About gRPC > [gRPC](https://grpc.io/about/) is a modern, open source, and high-performance RPC framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking, and authentication. It's also applicable in the last mile of distributed computing to connect devices, mobile applications, and browsers to backend services. @@ -491,6 +490,8 @@ As a side note, `CommonRuntime` will also be used later on for the client progra #### Runtime Implicits +For the server bootstrapping, remember adding `frees-rpc-server` dependency to your build. + Now, we need to implicitly provide two things: * A runtime interpreter of our `ServiceHandler` tied to a specific type. In our case, we'll use `cats.effects.IO`. @@ -560,6 +561,8 @@ Fortunately, once all the runtime requirements are in place (**`import gserver.i [frees-rpc] derives a client automatically based on the protocol. This is especially useful because you can distribute it depending on the protocol/service definitions. If you change something in your protocol definition, you will get a new client for free without having to write anything. +You will need to add either `frees-rpc-client-netty` or `frees-rpc-client-okhttp` to your build. + ### Client Runtime Similarly in this section, as we saw for the server case, we are defining all the client runtime configurations needed for communication with the server. diff --git a/modules/core/src/main/scala/RPCAsyncImplicits.scala b/modules/async/src/main/scala/RPCAsyncImplicits.scala similarity index 78% rename from modules/core/src/main/scala/RPCAsyncImplicits.scala rename to modules/async/src/main/scala/RPCAsyncImplicits.scala index 0c1bb20ba..6f36ad854 100644 --- a/modules/core/src/main/scala/RPCAsyncImplicits.scala +++ b/modules/async/src/main/scala/RPCAsyncImplicits.scala @@ -14,25 +14,18 @@ * limitations under the License. */ -package freestyle -package rpc +package freestyle.rpc +package async import cats.~> import cats.arrow.FunctionK -import cats.effect.{IO, Sync} -import freestyle.free.Capture +import cats.effect.IO import monix.eval.Task import monix.execution.Scheduler import scala.concurrent.Future -trait IOCapture { - - implicit def syncCapture[F[_]](implicit F: Sync[F]): Capture[F] = - new Capture[F] { def capture[A](a: => A): F[A] = F.delay(a) } -} - -trait AsyncInstances { +trait RPCAsyncImplicits { implicit val future2Task: Future ~> Task = λ[Future ~> Task] { fa => @@ -47,5 +40,3 @@ trait AsyncInstances { implicit val io2Task: IO ~> Task = λ[IO ~> Task](_.to[Task]) } - -trait RPCAsyncImplicits extends AsyncInstances diff --git a/modules/core/src/test/scala/client/ImplicitTests.scala b/modules/async/src/test/scala/ImplicitTests.scala similarity index 85% rename from modules/core/src/test/scala/client/ImplicitTests.scala rename to modules/async/src/test/scala/ImplicitTests.scala index 44b3d460c..f27fbef07 100644 --- a/modules/core/src/test/scala/client/ImplicitTests.scala +++ b/modules/async/src/test/scala/ImplicitTests.scala @@ -15,14 +15,15 @@ */ package freestyle.rpc -package client +package async import freestyle.free.FSHandler +import freestyle.rpc.common.RpcBaseTestSuite import monix.eval.Task import scala.concurrent.Future -class ImplicitTests extends RpcClientTestSuite { +class RPCAsyncImplicitsTests extends RpcBaseTestSuite with RPCAsyncImplicits { type FSHandlerTask2Future = FSHandler[Task, Future] @@ -32,13 +33,13 @@ class ImplicitTests extends RpcClientTestSuite { implicit val S: monix.execution.Scheduler = monix.execution.Scheduler.Implicits.global - freestyle.rpc.client.implicits.task2Future shouldBe a[FSHandlerTask2Future] + task2Future shouldBe a[FSHandlerTask2Future] } "fail compiling when the monix.execution.Scheduler implicit evidence is not present" in { shapeless.test.illTyped( - """freestyle.rpc.client.implicits.task2Future""", + """task2Future""", ".*Cannot find an implicit Scheduler, either import monix.execution.Scheduler.Implicits.global or use a custom one.*" ) } diff --git a/modules/core/src/main/scala/client/ChannelM.scala b/modules/client-netty/src/test/scala/ManagedChannelInterpreterNettyTests.scala similarity index 71% rename from modules/core/src/main/scala/client/ChannelM.scala rename to modules/client-netty/src/test/scala/ManagedChannelInterpreterNettyTests.scala index 2997ce538..65639b868 100644 --- a/modules/core/src/main/scala/client/ChannelM.scala +++ b/modules/client-netty/src/test/scala/ManagedChannelInterpreterNettyTests.scala @@ -17,16 +17,4 @@ package freestyle.rpc package client -import freestyle.free._ -import io.grpc.{CallOptions, ClientCall, MethodDescriptor} - -@free -trait ChannelM { - - def newCall[I, O]( - methodDescriptor: MethodDescriptor[I, O], - callOptions: CallOptions): FS[ClientCall[I, O]] - - def authority: FS[String] - -} +class ManagedChannelInterpreterNettyTests extends ManagedChannelInterpreterTests diff --git a/modules/core/src/main/scala/client/handlers/ChannelMHandler.scala b/modules/client-okhttp/src/test/scala/ManagedChannelInterpreterOkHttpTests.scala similarity index 51% rename from modules/core/src/main/scala/client/handlers/ChannelMHandler.scala rename to modules/client-okhttp/src/test/scala/ManagedChannelInterpreterOkHttpTests.scala index fcfb4d9ac..057730491 100644 --- a/modules/core/src/main/scala/client/handlers/ChannelMHandler.scala +++ b/modules/client-okhttp/src/test/scala/ManagedChannelInterpreterOkHttpTests.scala @@ -15,21 +15,6 @@ */ package freestyle.rpc -package client.handlers +package client -import cats.data.Kleisli -import freestyle.free.Capture -import freestyle.rpc.client.{ChannelM, ManagedChannelOps} -import io.grpc.{CallOptions, ClientCall, MethodDescriptor} - -class ChannelMHandler[M[_]](implicit C: Capture[M]) - extends ChannelM.Handler[ManagedChannelOps[M, ?]] { - - def newCall[I, O]( - methodDescriptor: MethodDescriptor[I, O], - callOptions: CallOptions): ManagedChannelOps[M, ClientCall[I, O]] = - Kleisli(ch => C.capture(ch.newCall(methodDescriptor, callOptions))) - - def authority: ManagedChannelOps[M, String] = - Kleisli(ch => C.capture(ch.authority())) -} +class ManagedChannelInterpreterOkHttpTests extends ManagedChannelInterpreterTests diff --git a/modules/core/src/main/scala/client/ManagedChannelConfig.scala b/modules/client/src/main/scala/ManagedChannelConfig.scala similarity index 100% rename from modules/core/src/main/scala/client/ManagedChannelConfig.scala rename to modules/client/src/main/scala/ManagedChannelConfig.scala diff --git a/modules/core/src/main/scala/proto/annotations.scala b/modules/client/src/main/scala/annotations.scala similarity index 73% rename from modules/core/src/main/scala/proto/annotations.scala rename to modules/client/src/main/scala/annotations.scala index 8ae52a4a0..eb76f0601 100644 --- a/modules/core/src/main/scala/proto/annotations.scala +++ b/modules/client/src/main/scala/annotations.scala @@ -17,7 +17,7 @@ package freestyle package rpc -import freestyle.rpc.internal.service.serviceImpl +import freestyle.rpc.internal.serviceImpl import scala.annotation.{compileTimeOnly, StaticAnnotation} @@ -29,17 +29,6 @@ package object protocol { inline def apply(defn: Any): Any = meta { serviceImpl.service(defn) } } - - class rpc(val serializationType: SerializationType) extends StaticAnnotation - - class stream[S <: StreamingType] extends StaticAnnotation - - class message extends StaticAnnotation - - class option(val name: String, val value: String, val quote: Boolean) extends StaticAnnotation - - @message - object Empty } // $COVERAGE-ON$ diff --git a/modules/core/src/main/scala/client/implicits.scala b/modules/client/src/main/scala/implicits.scala similarity index 92% rename from modules/core/src/main/scala/client/implicits.scala rename to modules/client/src/main/scala/implicits.scala index ac89def1c..1e2cc6281 100644 --- a/modules/core/src/main/scala/client/implicits.scala +++ b/modules/client/src/main/scala/implicits.scala @@ -14,11 +14,11 @@ * limitations under the License. */ -package freestyle -package rpc +package freestyle.rpc package client import freestyle.free._ +import freestyle.rpc.async.RPCAsyncImplicits object implicits extends CaptureInstances diff --git a/modules/core/src/main/scala/client/package.scala b/modules/client/src/main/scala/package.scala similarity index 100% rename from modules/core/src/main/scala/client/package.scala rename to modules/client/src/main/scala/package.scala diff --git a/modules/core/src/test/scala/client/ManagedChannelInterpreterTests.scala b/modules/client/src/test/scala/ManagedChannelInterpreterTests.scala similarity index 95% rename from modules/core/src/test/scala/client/ManagedChannelInterpreterTests.scala rename to modules/client/src/test/scala/ManagedChannelInterpreterTests.scala index 1f871366c..86ab83424 100644 --- a/modules/core/src/test/scala/client/ManagedChannelInterpreterTests.scala +++ b/modules/client/src/test/scala/ManagedChannelInterpreterTests.scala @@ -18,12 +18,13 @@ package freestyle.rpc package client import cats.data.Kleisli +import freestyle.rpc.common.SC import io.grpc.ManagedChannel import scala.concurrent.duration.Duration import scala.concurrent.{Await, Future} -class ManagedChannelInterpreterTests extends RpcClientTestSuite { +abstract class ManagedChannelInterpreterTests extends RpcClientTestSuite { import implicits._ diff --git a/modules/core/src/test/scala/client/RpcClientTestSuite.scala b/modules/client/src/test/scala/RpcClientTestSuite.scala similarity index 97% rename from modules/core/src/test/scala/client/RpcClientTestSuite.scala rename to modules/client/src/test/scala/RpcClientTestSuite.scala index 93769735d..2cea2ae00 100644 --- a/modules/core/src/test/scala/client/RpcClientTestSuite.scala +++ b/modules/client/src/test/scala/RpcClientTestSuite.scala @@ -21,6 +21,7 @@ import java.util.concurrent.{Callable, Executors} import com.google.common.util.concurrent.{ListenableFuture, ListeningExecutorService, MoreExecutors} import freestyle.rpc.client.utils.StringMarshaller +import freestyle.rpc.common.{RpcBaseTestSuite, SC} import io.grpc.{ClientCall, ManagedChannel, MethodDescriptor} trait RpcClientTestSuite extends RpcBaseTestSuite { diff --git a/modules/core/src/test/scala/client/utils/marshallers.scala b/modules/client/src/test/scala/utils/marshallers.scala similarity index 100% rename from modules/core/src/test/scala/client/utils/marshallers.scala rename to modules/client/src/test/scala/utils/marshallers.scala diff --git a/modules/common/src/main/scala/protocol.scala b/modules/common/src/main/scala/protocol.scala index 444d35255..8c7ce2edf 100644 --- a/modules/common/src/main/scala/protocol.scala +++ b/modules/common/src/main/scala/protocol.scala @@ -14,10 +14,11 @@ * limitations under the License. */ -package freestyle -package rpc +package freestyle.rpc package protocol +import scala.annotation.StaticAnnotation + sealed trait StreamingType extends Product with Serializable case object RequestStreaming extends StreamingType case object ResponseStreaming extends StreamingType @@ -26,3 +27,11 @@ case object BidirectionalStreaming extends StreamingType sealed trait SerializationType extends Product with Serializable case object Protobuf extends SerializationType case object Avro extends SerializationType + +class rpc(val serializationType: SerializationType) extends StaticAnnotation +class stream[S <: StreamingType] extends StaticAnnotation +class message extends StaticAnnotation +class option(val name: String, val value: String, val quote: Boolean) extends StaticAnnotation + +@message +object Empty diff --git a/modules/core/src/test/scala/RpcBaseTestSuite.scala b/modules/common/src/test/scala/RpcBaseTestSuite.scala similarity index 98% rename from modules/core/src/test/scala/RpcBaseTestSuite.scala rename to modules/common/src/test/scala/RpcBaseTestSuite.scala index d684bdcfd..9f85bf66a 100644 --- a/modules/core/src/test/scala/RpcBaseTestSuite.scala +++ b/modules/common/src/test/scala/RpcBaseTestSuite.scala @@ -15,6 +15,7 @@ */ package freestyle.rpc +package common import cats.data.Kleisli import org.scalamock.scalatest.MockFactory diff --git a/modules/core/src/test/scala/config.scala b/modules/common/src/test/scala/config.scala similarity index 97% rename from modules/core/src/test/scala/config.scala rename to modules/common/src/test/scala/config.scala index 3a5dcc76b..135e02b0a 100644 --- a/modules/core/src/test/scala/config.scala +++ b/modules/common/src/test/scala/config.scala @@ -15,6 +15,7 @@ */ package freestyle.rpc +package common object SC { diff --git a/modules/core/src/test/scala/models.scala b/modules/common/src/test/scala/models.scala similarity index 98% rename from modules/core/src/test/scala/models.scala rename to modules/common/src/test/scala/models.scala index cd0920a2d..752eac6e5 100644 --- a/modules/core/src/test/scala/models.scala +++ b/modules/common/src/test/scala/models.scala @@ -15,6 +15,7 @@ */ package freestyle.rpc +package common case class A(x: Int, y: Int) diff --git a/modules/config/src/test/scala/client/ChannelConfigTests.scala b/modules/config/src/test/scala/client/ChannelConfigTests.scala index be80e53d9..9202b95da 100644 --- a/modules/config/src/test/scala/client/ChannelConfigTests.scala +++ b/modules/config/src/test/scala/client/ChannelConfigTests.scala @@ -22,6 +22,7 @@ import cats.instances.try_._ import freestyle.free._ import freestyle.free.implicits._ import freestyle.free.config.implicits._ +import freestyle.rpc.common.SC import scala.util.{Success, Try} diff --git a/modules/config/src/test/scala/server/ServerConfigTests.scala b/modules/config/src/test/scala/server/ServerConfigTests.scala index 7c16b57df..f97c6cba8 100644 --- a/modules/config/src/test/scala/server/ServerConfigTests.scala +++ b/modules/config/src/test/scala/server/ServerConfigTests.scala @@ -22,6 +22,7 @@ import cats.implicits._ import freestyle.free._ import freestyle.free.implicits._ import freestyle.free.config.implicits._ +import freestyle.rpc.common.SC import scala.concurrent.{ExecutionContext, Future} diff --git a/modules/core/src/test/scala/client/handlers/ChannelHandlerTests.scala b/modules/core/src/test/scala/client/handlers/ChannelHandlerTests.scala deleted file mode 100644 index 01ca85a97..000000000 --- a/modules/core/src/test/scala/client/handlers/ChannelHandlerTests.scala +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2017-2018 47 Degrees, LLC. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package freestyle.rpc -package client.handlers - -import freestyle.rpc.client.RpcClientTestSuite -import io.grpc.{CallOptions, MethodDescriptor} - -import scala.concurrent.{ExecutionContext, Future} - -class ChannelHandlerTests extends RpcClientTestSuite { - - implicit val executionContext: ExecutionContext = ExecutionContext.Implicits.global - - import implicits._ - - val handler: ChannelMHandler[Future] = new ChannelMHandler[Future] - - "ChannelMHandler.Handler" should { - - "allow to perform new calls" in { - - (managedChannelMock - .newCall(_: MethodDescriptor[String, String], _: CallOptions)) - .expects(methodDescriptor, CallOptions.DEFAULT) - .returns(clientCallMock) - - runKFuture(handler.newCall(methodDescriptor, CallOptions.DEFAULT), managedChannelMock) shouldBe clientCallMock - } - - "allow to fetch the authority of the destination the channel connects to" in { - - (managedChannelMock.authority _: () => String).expects().returns(authority) - - runKFuture(handler.authority, managedChannelMock) shouldBe authority - } - - } - -} diff --git a/modules/core/src/test/scala/client/handlers/TaskMHandlerTests.scala b/modules/core/src/test/scala/client/handlers/TaskMHandlerTests.scala deleted file mode 100644 index 6d46e60d4..000000000 --- a/modules/core/src/test/scala/client/handlers/TaskMHandlerTests.scala +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2017-2018 47 Degrees, LLC. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package freestyle.rpc -package client.handlers - -import cats.~> -import freestyle.rpc.client.RpcClientTestSuite -import freestyle.rpc.client.implicits._ -import monix.eval.Task - -import scala.concurrent.duration.Duration -import scala.concurrent.{Await, Future} - -class TaskMHandlerTests extends RpcClientTestSuite { - - import implicits._ - - "TaskMHandler" should { - - "transform monix.eval.Task into any effect F, if an implicit evidence of " + - "freestyle.async.AsyncContext[F] is provided" in { - - implicit val S: monix.execution.Scheduler = monix.execution.Scheduler.Implicits.global - - val handler: Task ~> Future = task2Future - val fooTask: Task[String] = Task.now(foo) - - Await.result(handler(fooTask), Duration.Inf) shouldBe foo - } - - "recover from a failed monix.eval.Task wrapping them into scala.concurrent.Future" in { - - implicit val S: monix.execution.Scheduler = monix.execution.Scheduler.Implicits.global - - val handler: Task ~> Future = task2Future - val taskFailed: Task[String] = Task.raiseError(new RuntimeException(failureMessage)) - - Await.result(handler(taskFailed) recover { - case _ => failureMessage - }, Duration.Inf) shouldBe failureMessage - } - - } - -} diff --git a/modules/core/src/main/scala/internal/MonixAdapters.scala b/modules/internal/src/main/scala/MonixAdapters.scala similarity index 100% rename from modules/core/src/main/scala/internal/MonixAdapters.scala rename to modules/internal/src/main/scala/MonixAdapters.scala diff --git a/modules/core/src/main/scala/internal/client/calls.scala b/modules/internal/src/main/scala/client/calls.scala similarity index 98% rename from modules/core/src/main/scala/internal/client/calls.scala rename to modules/internal/src/main/scala/client/calls.scala index 395ccd243..093cacdb6 100644 --- a/modules/core/src/main/scala/internal/client/calls.scala +++ b/modules/internal/src/main/scala/client/calls.scala @@ -14,8 +14,7 @@ * limitations under the License. */ -package freestyle -package rpc +package freestyle.rpc package internal package client diff --git a/modules/core/src/main/scala/internal/service/GRPCServiceDefBuilder.scala b/modules/internal/src/main/scala/server/GRPCServiceDefBuilder.scala similarity index 100% rename from modules/core/src/main/scala/internal/service/GRPCServiceDefBuilder.scala rename to modules/internal/src/main/scala/server/GRPCServiceDefBuilder.scala diff --git a/modules/core/src/main/scala/internal/service/calls.scala b/modules/internal/src/main/scala/server/calls.scala similarity index 98% rename from modules/core/src/main/scala/internal/service/calls.scala rename to modules/internal/src/main/scala/server/calls.scala index 448bd4ca3..5bd294210 100644 --- a/modules/core/src/main/scala/internal/service/calls.scala +++ b/modules/internal/src/main/scala/server/calls.scala @@ -14,10 +14,9 @@ * limitations under the License. */ -package freestyle -package rpc +package freestyle.rpc package internal -package service +package server import cats.effect.{Effect, IO} import io.grpc.stub.ServerCalls.{ diff --git a/modules/core/src/main/scala/internal/service/service.scala b/modules/internal/src/main/scala/service.scala similarity index 96% rename from modules/core/src/main/scala/internal/service/service.scala rename to modules/internal/src/main/scala/service.scala index 5125068c8..85a97c47e 100644 --- a/modules/core/src/main/scala/internal/service/service.scala +++ b/modules/internal/src/main/scala/service.scala @@ -15,7 +15,7 @@ */ package freestyle.rpc -package internal.service +package internal import java.io.{ByteArrayInputStream, ByteArrayOutputStream, InputStream} @@ -174,9 +174,9 @@ private[internal] case class RPCRequest( val encodersImport: Import = serialization match { case Protobuf => - q"import _root_.freestyle.rpc.internal.service.encoders.pbd._" + q"import _root_.freestyle.rpc.internal.encoders.pbd._" case Avro => - q"import _root_.freestyle.rpc.internal.service.encoders.avro._" + q"import _root_.freestyle.rpc.internal.encoders.avro._" } def methodDescriptor = @@ -226,22 +226,22 @@ private[internal] case class RPCRequest( case Some(RequestStreaming) => q""" ($descriptorName, - _root_.io.grpc.stub.ServerCalls.asyncClientStreamingCall(_root_.freestyle.rpc.internal.service.calls.clientStreamingMethod(algebra.$name))) + _root_.io.grpc.stub.ServerCalls.asyncClientStreamingCall(_root_.freestyle.rpc.internal.server.calls.clientStreamingMethod(algebra.$name))) """ case Some(ResponseStreaming) => q""" ($descriptorName, - _root_.io.grpc.stub.ServerCalls.asyncServerStreamingCall(_root_.freestyle.rpc.internal.service.calls.serverStreamingMethod(algebra.$name))) + _root_.io.grpc.stub.ServerCalls.asyncServerStreamingCall(_root_.freestyle.rpc.internal.server.calls.serverStreamingMethod(algebra.$name))) """ case Some(BidirectionalStreaming) => q""" ($descriptorName, - _root_.io.grpc.stub.ServerCalls.asyncBidiStreamingCall(_root_.freestyle.rpc.internal.service.calls.bidiStreamingMethod(algebra.$name))) + _root_.io.grpc.stub.ServerCalls.asyncBidiStreamingCall(_root_.freestyle.rpc.internal.server.calls.bidiStreamingMethod(algebra.$name))) """ case None => q""" ($descriptorName, - _root_.io.grpc.stub.ServerCalls.asyncUnaryCall(_root_.freestyle.rpc.internal.service.calls.unaryMethod(algebra.$name))) + _root_.io.grpc.stub.ServerCalls.asyncUnaryCall(_root_.freestyle.rpc.internal.server.calls.unaryMethod(algebra.$name))) """ } } diff --git a/modules/core/src/test/scala/internal/GRPCServiceDefBuilderTests.scala b/modules/internal/src/test/scala/GRPCServiceDefBuilderTests.scala similarity index 97% rename from modules/core/src/test/scala/internal/GRPCServiceDefBuilderTests.scala rename to modules/internal/src/test/scala/GRPCServiceDefBuilderTests.scala index d18f9ed91..414dacbe2 100644 --- a/modules/core/src/test/scala/internal/GRPCServiceDefBuilderTests.scala +++ b/modules/internal/src/test/scala/GRPCServiceDefBuilderTests.scala @@ -17,6 +17,7 @@ package freestyle.rpc package internal +import freestyle.rpc.common.RpcBaseTestSuite import freestyle.rpc.internal.service.GRPCServiceDefBuilder import io.grpc._ import io.grpc.testing.TestMethodDescriptors diff --git a/modules/core/src/main/scala/server/GrpcConfig.scala b/modules/server/src/main/scala/GrpcConfig.scala similarity index 100% rename from modules/core/src/main/scala/server/GrpcConfig.scala rename to modules/server/src/main/scala/GrpcConfig.scala diff --git a/modules/core/src/main/scala/server/GrpcServer.scala b/modules/server/src/main/scala/GrpcServer.scala similarity index 100% rename from modules/core/src/main/scala/server/GrpcServer.scala rename to modules/server/src/main/scala/GrpcServer.scala diff --git a/modules/core/src/main/scala/server/handlers/GrpcServerHandler.scala b/modules/server/src/main/scala/handlers/GrpcServerHandler.scala similarity index 100% rename from modules/core/src/main/scala/server/handlers/GrpcServerHandler.scala rename to modules/server/src/main/scala/handlers/GrpcServerHandler.scala diff --git a/modules/core/src/main/scala/server/implicits.scala b/modules/server/src/main/scala/implicits.scala similarity index 86% rename from modules/core/src/main/scala/server/implicits.scala rename to modules/server/src/main/scala/implicits.scala index c0857cbdd..740d8ddbe 100644 --- a/modules/core/src/main/scala/server/implicits.scala +++ b/modules/server/src/main/scala/implicits.scala @@ -17,9 +17,10 @@ package freestyle.rpc package server +import cats.effect.Sync import cats.{~>, Monad} import freestyle.free._ -import freestyle.free.implicits._ +import freestyle.rpc.async.RPCAsyncImplicits import freestyle.rpc.server.handlers.GrpcServerHandler trait ServerImplicits { @@ -39,6 +40,12 @@ trait Syntax { } } +trait SyncCapture { + + implicit def syncCapture[F[_]](implicit F: Sync[F]): Capture[F] = + new Capture[F] { def capture[A](a: => A): F[A] = F.delay(a) } +} + trait Helpers { def server[M[_]](implicit S: GrpcServer[M]): FreeS[M, Unit] = { @@ -53,7 +60,7 @@ trait Helpers { object implicits extends CaptureInstances - with IOCapture + with SyncCapture with RPCAsyncImplicits with Syntax with Helpers diff --git a/modules/core/src/main/scala/server/package.scala b/modules/server/src/main/scala/package.scala similarity index 100% rename from modules/core/src/main/scala/server/package.scala rename to modules/server/src/main/scala/package.scala diff --git a/modules/core/src/test/scala/CommonUtils.scala b/modules/server/src/test/scala/server/CommonUtils.scala similarity index 98% rename from modules/core/src/test/scala/CommonUtils.scala rename to modules/server/src/test/scala/server/CommonUtils.scala index ed2ccfe4c..cacf993c2 100644 --- a/modules/core/src/test/scala/CommonUtils.scala +++ b/modules/server/src/test/scala/server/CommonUtils.scala @@ -17,6 +17,7 @@ package freestyle.rpc import cats.effect.IO +import freestyle.rpc.common._ import freestyle.rpc.client._ import freestyle.rpc.server._ diff --git a/modules/core/src/test/scala/server/GrpcServerTests.scala b/modules/server/src/test/scala/server/GrpcServerTests.scala similarity index 98% rename from modules/core/src/test/scala/server/GrpcServerTests.scala rename to modules/server/src/test/scala/server/GrpcServerTests.scala index 0426ec4a1..542e609bf 100644 --- a/modules/core/src/test/scala/server/GrpcServerTests.scala +++ b/modules/server/src/test/scala/server/GrpcServerTests.scala @@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit import cats.Id import cats.implicits._ import freestyle.free._ +import freestyle.rpc.common.SC import io.grpc.{Server, ServerServiceDefinition} class GrpcServerTests extends RpcServerTestSuite { diff --git a/modules/core/src/test/scala/server/HelperTests.scala b/modules/server/src/test/scala/server/HelperTests.scala similarity index 100% rename from modules/core/src/test/scala/server/HelperTests.scala rename to modules/server/src/test/scala/server/HelperTests.scala diff --git a/modules/core/src/test/scala/RPCTests.scala b/modules/server/src/test/scala/server/RPCTests.scala similarity index 99% rename from modules/core/src/test/scala/RPCTests.scala rename to modules/server/src/test/scala/server/RPCTests.scala index b83b1b95b..e7d3a3f3c 100644 --- a/modules/core/src/test/scala/RPCTests.scala +++ b/modules/server/src/test/scala/server/RPCTests.scala @@ -18,6 +18,7 @@ package freestyle.rpc import freestyle.free._ import org.scalatest._ +import freestyle.rpc.common._ import freestyle.rpc.server._ import freestyle.rpc.Utils.clientProgram.MyRPCClient import freestyle.rpc.protocol.Empty diff --git a/modules/core/src/test/scala/server/RpcServerTestSuite.scala b/modules/server/src/test/scala/server/RpcServerTestSuite.scala similarity index 98% rename from modules/core/src/test/scala/server/RpcServerTestSuite.scala rename to modules/server/src/test/scala/server/RpcServerTestSuite.scala index c9c96eefa..6bda50daf 100644 --- a/modules/core/src/test/scala/server/RpcServerTestSuite.scala +++ b/modules/server/src/test/scala/server/RpcServerTestSuite.scala @@ -20,6 +20,7 @@ package server import java.util.concurrent.TimeUnit import cats.{~>, Id} +import freestyle.rpc.common.{RpcBaseTestSuite, SC} import io.grpc.{Server, ServerServiceDefinition} import scala.collection.JavaConverters._ diff --git a/modules/core/src/test/scala/server/ServerConfigTests.scala b/modules/server/src/test/scala/server/ServerConfigTests.scala similarity index 97% rename from modules/core/src/test/scala/server/ServerConfigTests.scala rename to modules/server/src/test/scala/server/ServerConfigTests.scala index e76dadb24..9243d0b44 100644 --- a/modules/core/src/test/scala/server/ServerConfigTests.scala +++ b/modules/server/src/test/scala/server/ServerConfigTests.scala @@ -19,6 +19,7 @@ package server import cats.Id import cats.data.Kleisli +import freestyle.rpc.common.SC import io.grpc.Server import scala.collection.JavaConverters._ diff --git a/modules/core/src/main/scala/client/handlers/TaskMHandler.scala b/modules/server/src/test/scala/server/SyncCaptureTests.scala similarity index 54% rename from modules/core/src/main/scala/client/handlers/TaskMHandler.scala rename to modules/server/src/test/scala/server/SyncCaptureTests.scala index 1bbc3170e..c1c4f4d8e 100644 --- a/modules/core/src/main/scala/client/handlers/TaskMHandler.scala +++ b/modules/server/src/test/scala/server/SyncCaptureTests.scala @@ -14,25 +14,28 @@ * limitations under the License. */ -package freestyle -package rpc -package client.handlers +package freestyle.rpc +package server -import freestyle.async.AsyncContext -import freestyle.free.FSHandler -import monix.eval.{Callback, Task} -import monix.execution.Scheduler +import cats.effect.IO +import freestyle.free.Capture -class TaskMHandler[F[_]](implicit AC: AsyncContext[F], S: Scheduler) extends FSHandler[Task, F] { +class SyncCaptureTests extends RpcServerTestSuite { - override def apply[A](fa: Task[A]): F[A] = AC.runAsync { cb => - fa.runAsync { - new Callback[A] { - override def onSuccess(value: A): Unit = cb(Right(value)) + "SyncCapture" should { - override def onError(ex: Throwable): Unit = cb(Left(ex)) - } + "work as expected" in { + + val foo: String = "foo" + val instance = new SyncCapture {} + + import instance._ + + def a(implicit C: Capture[IO]) = C.capture(foo) + + a.unsafeRunSync() shouldBe foo } - (): Unit + } + } diff --git a/modules/core/src/test/scala/server/SyntaxTests.scala b/modules/server/src/test/scala/server/SyntaxTests.scala similarity index 100% rename from modules/core/src/test/scala/server/SyntaxTests.scala rename to modules/server/src/test/scala/server/SyntaxTests.scala diff --git a/modules/core/src/test/scala/TaglessRPCTests.scala b/modules/server/src/test/scala/server/TaglessRPCTests.scala similarity index 99% rename from modules/core/src/test/scala/TaglessRPCTests.scala rename to modules/server/src/test/scala/server/TaglessRPCTests.scala index d634c786b..8b7a24bc9 100644 --- a/modules/core/src/test/scala/TaglessRPCTests.scala +++ b/modules/server/src/test/scala/server/TaglessRPCTests.scala @@ -18,6 +18,7 @@ package freestyle.rpc import freestyle.free._ import org.scalatest._ +import freestyle.rpc.common._ import freestyle.rpc.server._ import freestyle.rpc.TaglessUtils.clientProgram.MyRPCClient import freestyle.rpc.protocol.Empty diff --git a/modules/core/src/test/scala/TaglessUtils.scala b/modules/server/src/test/scala/server/TaglessUtils.scala similarity index 99% rename from modules/core/src/test/scala/TaglessUtils.scala rename to modules/server/src/test/scala/server/TaglessUtils.scala index 71d62a205..2277d910e 100644 --- a/modules/core/src/test/scala/TaglessUtils.scala +++ b/modules/server/src/test/scala/server/TaglessUtils.scala @@ -19,6 +19,7 @@ package freestyle.rpc import cats.{~>, Monad, MonadError} import freestyle.free._ import freestyle.free.asyncCatsEffect.implicits._ +import freestyle.rpc.common._ import freestyle.rpc.protocol._ import monix.eval.Task import monix.reactive.Observable diff --git a/modules/core/src/test/scala/Utils.scala b/modules/server/src/test/scala/server/Utils.scala similarity index 99% rename from modules/core/src/test/scala/Utils.scala rename to modules/server/src/test/scala/server/Utils.scala index 82f80ac61..ee6f4758c 100644 --- a/modules/core/src/test/scala/Utils.scala +++ b/modules/server/src/test/scala/server/Utils.scala @@ -18,7 +18,7 @@ package freestyle.rpc import cats.{~>, Monad, MonadError} import freestyle.free._ -import freestyle.rpc.Utils.database.a4 +import freestyle.rpc.common._ import freestyle.free.asyncCatsEffect.implicits._ import freestyle.rpc.protocol._ import monix.eval.Task diff --git a/modules/core/src/test/scala/server/handlers/GrpcServerHandlerTests.scala b/modules/server/src/test/scala/server/handlers/GrpcServerHandlerTests.scala similarity index 99% rename from modules/core/src/test/scala/server/handlers/GrpcServerHandlerTests.scala rename to modules/server/src/test/scala/server/handlers/GrpcServerHandlerTests.scala index a8260a251..f687f3ba2 100644 --- a/modules/core/src/test/scala/server/handlers/GrpcServerHandlerTests.scala +++ b/modules/server/src/test/scala/server/handlers/GrpcServerHandlerTests.scala @@ -17,6 +17,7 @@ package freestyle.rpc package server.handlers +import freestyle.rpc.common.SC import freestyle.rpc.server.RpcServerTestSuite import io.grpc.{Server, ServerServiceDefinition} diff --git a/project/ProjectPlugin.scala b/project/ProjectPlugin.scala index 32ec8c1bf..e52b2460d 100644 --- a/project/ProjectPlugin.scala +++ b/project/ProjectPlugin.scala @@ -25,18 +25,35 @@ object ProjectPlugin extends AutoPlugin { } lazy val commonSettings: Seq[Def.Setting[_]] = Seq( - scalacOptions := Seq("-deprecation", "-encoding", "UTF-8", "-feature", "-unchecked") + scalacOptions := Seq( + "-deprecation", + "-encoding", + "UTF-8", + "-feature", + "-unchecked", + "-language:higherKinds"), + libraryDependencies ++= Seq( + %%("cats-core") % Test, + %%("scalamockScalatest") % Test + ) ) - lazy val coreSettings: Seq[Def.Setting[_]] = Seq( + lazy val asyncSettings: Seq[Def.Setting[_]] = Seq( libraryDependencies ++= Seq( - %%("frees-core", V.frees), - %%("frees-async", V.frees), + %%("cats-core"), + %%("cats-effect"), + %%("monix"), + %%("shapeless") % Test, + %%("frees-core") % Test + ) + ) + + lazy val internalSettings: Seq[Def.Setting[_]] = Seq( + libraryDependencies ++= Seq( + %%("cats-effect"), %%("frees-async-guava", V.frees) exclude ("com.google.guava", "guava"), - %%("frees-async-cats-effect", V.frees), %("grpc-core", V.grpc), %("grpc-stub", V.grpc), - %("grpc-netty", V.grpc), %%("monix"), %%("pbdirect", V.pbdirect), "com.sksamuel.avro4s" %% "avro4s-core" % V.avro4s, @@ -45,6 +62,36 @@ object ProjectPlugin extends AutoPlugin { ) ) + lazy val clientCoreSettings: Seq[Def.Setting[_]] = Seq( + libraryDependencies ++= Seq( + %%("frees-async-cats-effect", V.frees), + %("grpc-testing", V.grpc) % Test, + %%("scalamockScalatest") % Test + ) + ) + + lazy val clientNettySettings: Seq[Def.Setting[_]] = Seq( + libraryDependencies ++= Seq( + %("grpc-netty", V.grpc) + ) + ) + + lazy val clientOkHttpSettings: Seq[Def.Setting[_]] = Seq( + libraryDependencies ++= Seq( + %("grpc-okhttp", V.grpc) + ) + ) + + lazy val serverSettings: Seq[Def.Setting[_]] = Seq( + libraryDependencies ++= Seq( + %%("frees-async-cats-effect", V.frees), + %("grpc-core", V.grpc), + %("grpc-netty", V.grpc), + %("grpc-testing", V.grpc) % Test, + %%("scalamockScalatest") % Test + ) + ) + lazy val configSettings = Seq( libraryDependencies ++= Seq( %%("frees-config", V.frees),