Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decouple frees config #300

Merged
merged 8 commits into from
Jun 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions docs/src/main/tut/core-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,11 @@ trait CommonRuntime {
```

```tut:silent
import cats.effect.IO
import cats.implicits._
import freestyle.free.config.implicits._
import freestyle.async.catsEffect.implicits._
import freestyle.rpc._
import freestyle.rpc.config._
import freestyle.rpc.client._
import freestyle.rpc.client.config._
import freestyle.rpc.client.implicits._
Expand All @@ -241,12 +242,7 @@ import scala.util.{Failure, Success, Try}
trait Implicits extends CommonRuntime {

val channelFor: ChannelFor =
ConfigForAddress[Try]("rpc.host", "rpc.port") match {
case Success(c) => c
case Failure(e) =>
e.printStackTrace()
throw new RuntimeException("Unable to load the client configuration", e)
}
ConfigForAddress[IO]("rpc.host", "rpc.port").unsafeRunSync

implicit val serviceClient: Greeter.Client[Task] =
Greeter.client[Task](channelFor, options = CallOptions.DEFAULT.withCompression("gzip"))
Expand Down
11 changes: 3 additions & 8 deletions docs/src/main/tut/metrics-reporting.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ In this case, in order to intercept the client calls we need additional configur
```tut:silent
import cats.implicits._
import cats.effect.IO
import freestyle.free.config.implicits._
import freestyle.async.catsEffect.implicits._
import freestyle.rpc._
import freestyle.rpc.config._
import freestyle.rpc.client._
import freestyle.rpc.client.config._
import freestyle.rpc.client.implicits._
Expand All @@ -119,12 +119,7 @@ import freestyle.rpc.prometheus.client.MonitoringClientInterceptor
object InterceptingClientCalls extends CommonRuntime {

val channelFor: ChannelFor =
ConfigForAddress[Try]("rpc.host", "rpc.port") match {
case Success(c) => c
case Failure(e) =>
e.printStackTrace()
throw new RuntimeException("Unable to load the client configuration", e)
}
ConfigForAddress[IO]("rpc.host", "rpc.port").unsafeRunSync

implicit val serviceClient: Greeter.Client[Task] =
Greeter.client[Task](
Expand Down Expand Up @@ -169,4 +164,4 @@ configuration.collectorRegistry.register(new DropwizardExports(metrics))
[Monix]: https://monix.io/
[cats-effect]: https://github.com/typelevel/cats-effect
[Metrifier]: https://github.com/47deg/metrifier
[frees-config]: http://frees.io/docs/patterns/config/
[frees-config]: http://frees.io/docs/patterns/config/
11 changes: 3 additions & 8 deletions docs/src/main/tut/patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,9 @@ So, taking into account all we have just said, how would our code look?
```tut:silent
import cats.implicits._
import cats.effect.IO
import freestyle.free.config.implicits._
import freestyle.async.catsEffect.implicits._
import freestyle.rpc._
import freestyle.rpc.config._
import freestyle.rpc.client._
import freestyle.rpc.client.config._
import freestyle.rpc.client.implicits._
Expand All @@ -297,12 +297,7 @@ object gclient {
trait Implicits extends CommonRuntime {

val channelFor: ChannelFor =
ConfigForAddress[Try]("rpc.host", "rpc.port") match {
case Success(c) => c
case Failure(e) =>
e.printStackTrace()
throw new RuntimeException("Unable to load the client configuration", e)
}
ConfigForAddress[IO]("rpc.host", "rpc.port").unsafeRunSync

implicit val serviceClient: Greeter.Client[Task] =
Greeter.client[Task](channelFor)
Expand Down Expand Up @@ -355,4 +350,4 @@ object RPCDemoApp {
[Monix]: https://monix.io/
[cats-effect]: https://github.com/typelevel/cats-effect
[Metrifier]: https://github.com/47deg/metrifier
[frees-config]: http://frees.io/docs/patterns/config/
[frees-config]: http://frees.io/docs/patterns/config/
44 changes: 29 additions & 15 deletions modules/config/src/main/scala/client/ChannelConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,41 @@ package freestyle.rpc
package client
package config

import cats.Functor
import cats.syntax.either._
import cats.effect.Sync
import cats.syntax.functor._
import freestyle.tagless._
import freestyle.tagless.config.ConfigM
import cats.syntax.flatMap._
import cats.syntax.either._

@module
trait ChannelConfig {
import freestyle.rpc.config.ConfigM

implicit val functor: Functor
import com.typesafe.config.ConfigException.Missing

class ChannelConfig[F[_]](implicit S: Sync[F], C: ConfigM[F]) {

val configM: ConfigM
val defaultHost: String = "localhost"
val defaultPort: Int = freestyle.rpc.server.defaultPort

def loadChannelAddress(hostPath: String, portPath: String): FS[ChannelForAddress] =
configM.load map (config =>
ChannelForAddress(
config.string(hostPath).getOrElse(defaultHost),
config.int(portPath).getOrElse(defaultPort)))
def loadChannelAddress(hostPath: String, portPath: String): F[ChannelForAddress] =
for {
config <- C.load
host <- S.pure(
Either
.catchOnly[Missing](config.getString(hostPath)))
port <- S.pure(Either.catchOnly[Missing](config.getInt(portPath)))
} yield ChannelForAddress(host.getOrElse(defaultHost), port.getOrElse(defaultPort))

def loadChannelTarget(targetPath: String): F[ChannelForTarget] =
for {
config <- C.load
target <- S.pure(Either.catchOnly[Missing](config.getString(targetPath)))
} yield ChannelForTarget(target.getOrElse("target"))

}

object ChannelConfig {
def apply[F[_]](implicit S: Sync[F], C: ConfigM[F]): ChannelConfig[F] =
new ChannelConfig[F]

def loadChannelTarget(targetPath: String): FS[ChannelForTarget] =
configM.load map (config => ChannelForTarget(config.string(targetPath).getOrElse("target")))
implicit def defaultChannelConfig[F[_]](implicit S: Sync[F], C: ConfigM[F]): ChannelConfig[F] =
apply[F](S, C)
}
33 changes: 33 additions & 0 deletions modules/config/src/main/scala/config.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2017-2018 47 Degrees, LLC. <http://www.47deg.com>
*
* 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

import cats.effect.Sync
import pureconfig._
import com.typesafe.config.{Config, ConfigFactory}

object config {

trait ConfigM[F[_]] {
def load: F[Config]
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we could add a new method to this algebra:

def get[A](from: (Config) => A): F[Either[Missing, A]]

With the implementation:

def get[A](getValue: => A): F[Either[Missing, A]] =
  S.pure(Either.catchOnly[Missing](getValue))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that, at some point in the near future, we'll reintroduce frees-config, and we could maybe add it there? this implementation is temporary. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good


implicit def syncConfigM[F[_]](implicit F: Sync[F]): ConfigM[F] = new ConfigM[F] {
def load: F[Config] = F.delay(loadConfigOrThrow[Config](ConfigFactory.load()))
}

}
45 changes: 28 additions & 17 deletions modules/config/src/main/scala/server/ServerConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,37 @@ package freestyle.rpc
package server
package config

import cats.Functor
import cats.syntax.either._
import cats.effect.Sync
import cats.syntax.flatMap._
import cats.syntax.functor._
import freestyle.tagless._
import freestyle.tagless.config.ConfigM
import cats.syntax.either._

import freestyle.rpc.config.ConfigM

@module
trait ServerConfig {
import com.typesafe.config.ConfigException.Missing

val configM: ConfigM
implicit val functor: Functor
class ServerConfig[F[_]](implicit S: Sync[F], C: ConfigM[F]) {

def buildServer(portPath: String, configList: List[GrpcConfig] = Nil): F[ServerW] =
for {
config <- C.load
port <- S.pure(
Either
.catchOnly[Missing](config.getInt(portPath)))
} yield ServerW.default(port.getOrElse(defaultPort), configList)

def buildNettyServer(portPath: String, configList: List[GrpcConfig] = Nil): F[ServerW] =
for {
config <- C.load
port <- S.pure(
Either
.catchOnly[Missing](config.getInt(portPath)))
} yield ServerW.netty(ChannelForPort(port.getOrElse(defaultPort)), configList)
}

def buildServer(portPath: String, configList: List[GrpcConfig] = Nil): FS[ServerW] =
configM.load.map { config =>
val port = config.int(portPath).getOrElse(defaultPort)
ServerW.default(port, configList)
}
object ServerConfig {
def apply[F[_]](implicit S: Sync[F], C: ConfigM[F]): ServerConfig[F] = new ServerConfig[F]

def buildNettyServer(portPath: String, configList: List[GrpcConfig] = Nil): FS[ServerW] =
configM.load.map { config =>
ServerW.netty(ChannelForPort(config.int(portPath).getOrElse(defaultPort)), configList)
}
implicit def defaultServerConfig[F[_]](implicit S: Sync[F], C: ConfigM[F]): ServerConfig[F] =
apply[F](S, C)
}
13 changes: 5 additions & 8 deletions modules/config/src/test/scala/client/ChannelConfigTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,21 @@ package freestyle.rpc
package client
package config

import cats.instances.try_._
import freestyle.tagless.config.implicits._
import freestyle.rpc.common.SC

import scala.util.{Success, Try}
import freestyle.rpc.common.{ConcurrentMonad, SC}

class ChannelConfigTests extends RpcClientTestSuite {

"ChannelConfig" should {

"for Address [host, port] work as expected" in {

ConfigForAddress[Try](SC.host, SC.port.toString) shouldBe a[Success[_]]
ConfigForAddress[ConcurrentMonad](SC.host, SC.port.toString).unsafeRunSync shouldBe ChannelForAddress(
"localhost",
50051)
}

"for Target work as expected" in {

ConfigForTarget[Try](SC.host) shouldBe a[Success[_]]
ConfigForTarget[ConcurrentMonad](SC.host).unsafeRunSync shouldBe ChannelForTarget("target")
}

}
Expand Down
3 changes: 1 addition & 2 deletions modules/config/src/test/scala/server/ServerConfigTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package freestyle.rpc
package server
package config

import freestyle.tagless.config.implicits._
import freestyle.rpc.common.{ConcurrentMonad, SC}

import scala.concurrent.ExecutionContext
Expand All @@ -27,7 +26,7 @@ class ServerConfigTests extends RpcServerTestSuite {

implicit val ec: ExecutionContext = ExecutionContext.Implicits.global

"ServerConfig.Op" should {
"ServerConfig" should {

"load the port specified in the config file" in {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package example.routeguide.client.runtime
import cats.effect.IO
import freestyle.rpc.ChannelFor
import freestyle.rpc.client.config.ConfigForAddress
import freestyle.tagless.config.implicits._

trait ClientConf {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import cats.effect.IO
import freestyle.rpc.server._
import freestyle.rpc.server.config.BuildServerFromConfig
import freestyle.rpc.server.{AddService, GrpcConfig, ServerW}
import freestyle.tagless.config.implicits._
import example.routeguide.server.handlers.RouteGuideServiceHandler
import example.routeguide.protocol.Protocols.RouteGuideService
import example.routeguide.runtime._
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import cats.effect.IO
import examples.todolist.client.handlers._
import examples.todolist.protocol.Protocols._
import freestyle.tagless.loggingJVM.log4s.implicits._
import freestyle.tagless.config.implicits._
import examples.todolist.runtime.CommonRuntime
import freestyle.rpc.ChannelFor
import freestyle.rpc.client.config.ConfigForAddress
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import examples.todolist.server.handlers._
import freestyle.rpc.server._
import freestyle.rpc.server.config.BuildServerFromConfig
import freestyle.rpc.server.{AddService, GrpcConfig, ServerW}
import freestyle.tagless.config.implicits._
import freestyle.tagless.loggingJVM.log4s.implicits._
import java.util.Properties

Expand Down
6 changes: 3 additions & 3 deletions project/ProjectPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ object ProjectPlugin extends AutoPlugin {
val avrohugger: String = "1.0.0-RC10"
val catsEffect: String = "0.10.1"
val circe: String = "0.9.3"
val frees: String = "0.8.0"
val frees: String = "0.8.1"
val fs2ReactiveStreams: String = "0.5.1"
val grpc: String = "1.11.0"
val log4s: String = "1.6.1"
Expand Down Expand Up @@ -92,7 +92,7 @@ object ProjectPlugin extends AutoPlugin {

lazy val configSettings = Seq(
libraryDependencies ++= Seq(
%%("frees-config", V.frees)
%%("pureconfig")
)
)

Expand Down Expand Up @@ -164,7 +164,7 @@ object ProjectPlugin extends AutoPlugin {

lazy val exampleTodolistCommonSettings: Seq[Def.Setting[_]] = Seq(
libraryDependencies ++= Seq(
"io.frees" %% "frees-todolist-lib" % "0.8.1-SNAPSHOT",
"io.frees" %% "frees-todolist-lib" % V.frees,
%%("log4s", V.log4s),
%("logback-classic", V.logback)
)
Expand Down
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
resolvers += Resolver.sonatypeRepo("releases")
resolvers += Resolver.sonatypeRepo("snapshots")

addSbtPlugin("io.frees" % "sbt-freestyle" % "0.3.21")
addSbtPlugin("io.frees" % "sbt-freestyle" % "0.3.23")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.8.0")

libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value