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

Add seed sample #598

Merged
merged 14 commits into from Apr 17, 2019
175 changes: 166 additions & 9 deletions build.sbt
Expand Up @@ -119,7 +119,7 @@ lazy val server = project
//// PROMETHEUS ////
////////////////////

lazy val `prometheus` = project
lazy val prometheus = project
.in(file("modules/metrics/prometheus"))
.dependsOn(`internal-core` % "compile->compile;test->test")
.dependsOn(testing % "test->test")
Expand All @@ -130,7 +130,7 @@ lazy val `prometheus` = project
//// DROPWIZARD ////
////////////////////

lazy val `dropwizard` = project
lazy val dropwizard = project
.in(file("modules/metrics/dropwizard"))
.dependsOn(`internal-core` % "compile->compile;test->test")
.dependsOn(testing % "test->test")
Expand All @@ -141,7 +141,7 @@ lazy val `dropwizard` = project
//// HTTP/REST ////
///////////////////

lazy val `http` = project
lazy val http = project
.in(file("modules/http"))
.dependsOn(common % "compile->compile;test->test")
.dependsOn(server % "compile->compile;test->test")
Expand Down Expand Up @@ -187,7 +187,7 @@ lazy val `idlgen-sbt` = project
//// BENCHMARKS ////
////////////////////

lazy val lastReleasedV = "0.17.2"
lazy val lastReleasedV = "0.18.0"

lazy val `benchmarks-vprev` = project
.in(file("benchmarks/vprev"))
Expand Down Expand Up @@ -273,6 +273,162 @@ lazy val `example-routeguide-client` = project
.settings(
addCommandAlias("runClientTask", "runMain example.routeguide.client.task.ClientAppTask"))

////////////////////
///// SEED /////
////////////////////

////////////////////////
//// Shared Modules ////
////////////////////////

lazy val seed_config = project
.in(file("modules/examples/seed/shared/modules/config"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)
.settings(exampleSeedConfigSettings)

////////////////////////
//// Shared ////
////////////////////////

lazy val allSharedModules: Seq[ProjectReference] = Seq(
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved
seed_config
)

lazy val allSharedModulesDeps: Seq[ClasspathDependency] =
allSharedModules.map(ClasspathDependency(_, None))

lazy val seed_shared = project
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved
.in(file("modules/examples/seed/shared"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)
.aggregate(allSharedModules: _*)
.dependsOn(allSharedModulesDeps: _*)

//////////////////////////
//// Server Modules ////
//////////////////////////

lazy val seed_server_common = project
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved
.in(file("modules/examples/seed/server/modules/common"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)

lazy val seed_server_protocol_avro = project
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved
.in(file("modules/examples/seed/server/modules/protocol_avro"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)
.dependsOn(fs2)
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved

lazy val seed_server_protocol_proto = project
.in(file("modules/examples/seed/server/modules/protocol_proto"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)
.dependsOn(fs2)

lazy val seed_server_process = project
.in(file("modules/examples/seed/server/modules/process"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)
.settings(exampleSeedLogSettings)
.dependsOn(seed_server_common, seed_server_protocol_avro, seed_server_protocol_proto)

lazy val seed_server_app = project
.in(file("modules/examples/seed/server/modules/app"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)
.dependsOn(server, seed_server_process, seed_config)

//////////////////////////
//// Server ////
//////////////////////////

lazy val allServerModules: Seq[ProjectReference] = Seq(
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved
seed_server_common,
seed_server_protocol_avro,
seed_server_protocol_proto,
seed_server_process,
seed_server_app
)

lazy val allServerModulesDeps: Seq[ClasspathDependency] =
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved
allServerModules.map(ClasspathDependency(_, None))
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved

lazy val seed_server = project
.in(file("modules/examples/seed/server"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)
.aggregate(allServerModules: _*)
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved
.dependsOn(allServerModulesDeps: _*)
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved
addCommandAlias("runAvroServer", "seed_server/runMain example.seed.server.app.AvroServerApp")
addCommandAlias("runProtoServer", "seed_server/runMain example.seed.server.app.ProtoServerApp")

//////////////////////////
//// Client Modules ////
//////////////////////////

lazy val seed_client_common = project
.in(file("modules/examples/seed/client/modules/common"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)

lazy val seed_client_process = project
.in(file("modules/examples/seed/client/modules/process"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)
.settings(exampleSeedLogSettings)
.dependsOn(netty, fs2, seed_client_common, seed_server_protocol_avro, seed_server_protocol_proto)

lazy val seed_client_app = project
.in(file("modules/examples/seed/client/modules/app"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)
.settings(exampleSeedClientAppSettings)
.dependsOn(seed_client_process, seed_config)

//////////////////////////
//// Client ////
//////////////////////////

lazy val allClientModules: Seq[ProjectReference] = Seq(
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved
seed_client_common,
seed_client_process,
seed_client_app
)

lazy val allClientModulesDeps: Seq[ClasspathDependency] =
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved
allClientModules.map(ClasspathDependency(_, None))

lazy val seed_client = project
.in(file("modules/examples/seed/client"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)
.aggregate(allClientModules: _*)
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved
.dependsOn(allClientModulesDeps: _*)
AdrianRaFo marked this conversation as resolved.
Show resolved Hide resolved
addCommandAlias("runAvroClient", "seed_client/runMain example.seed.client.app.AvroClientApp")
addCommandAlias("runProtoClient", "seed_client/runMain example.seed.client.app.ProtoClientApp")

/////////////////////////
//// Root ////
/////////////////////////

lazy val allSeedModules: Seq[ProjectReference] = Seq(
seed_shared,
seed_client,
seed_server
)

lazy val allSeedModulesDeps: Seq[ClasspathDependency] =
allSeedModules.map(ClasspathDependency(_, None))

lazy val seed = project
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason for having this module?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

One module to rule(and compile) them all

Copy link
Contributor

Choose a reason for hiding this comment

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

giphy

.in(file("modules/examples/seed"))
.settings(coverageEnabled := false)
.settings(noPublishSettings)
.settings(moduleName := "mu-rpc-example-seed")
.aggregate(allSeedModules: _*)
.dependsOn(allSeedModulesDeps: _*)

////////////////////
//// TODOLIST ////
////////////////////
Expand Down Expand Up @@ -357,16 +513,16 @@ lazy val allModules: Seq[ProjectReference] = Seq(
monix,
fs2,
`client-cache`,
`netty`,
`okhttp`,
netty,
okhttp,
server,
config,
`dropwizard`,
`prometheus`,
dropwizard,
prometheus,
testing,
ssl,
`idlgen-core`,
`http`,
http,
`marshallers-jodatime`,
`example-routeguide-protocol`,
`example-routeguide-common`,
Expand All @@ -377,6 +533,7 @@ lazy val allModules: Seq[ProjectReference] = Seq(
`example-todolist-runtime`,
`example-todolist-server`,
`example-todolist-client`,
seed,
`benchmarks-vprev`,
`benchmarks-vnext`,
`legacy-avro-decimal-compat-model`,
Expand Down
@@ -0,0 +1,3 @@
name = "SeedClient"
host = "localhost"
port = 19683
fedefernandez marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<withJansi>true</withJansi>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout name="l_info" class="ch.qos.logback.classic.PatternLayout">
<Pattern>
[%highlight(%-5level)] %msg%n
</Pattern>
</layout>
</encoder>
</appender>

<root level="info">
<appender-ref ref="STDOUT"/>
</root>

</configuration>
@@ -0,0 +1,41 @@
/*
* Copyright 2017-2019 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 example.seed.client.app

import cats.effect._
import example.seed.client.common.models._
import fs2.Stream
import io.chrisdavenport.log4cats.Logger

class AvroClientProgram[F[_]: ConcurrentEffect: ContextShift] extends ClientBoot[F] {

def clientProgram(config: SeedClientConfig)(implicit L: Logger[F]): Stream[F, ExitCode] = {
for {
peopleClient <- avroPeopleServiceClient(config.client.host, config.client.port)
result <- Stream.eval(peopleClient.getPerson(config.params.request))
} yield result.fold(_ => ExitCode.Error, _ => ExitCode.Success)
}
}

object AvroClientApp extends IOApp {
def run(args: List[String]): IO[ExitCode] =
new AvroClientProgram[IO]
.runProgram(args)
.compile
.toList
.map(_.headOption.getOrElse(ExitCode.Error))
}
@@ -0,0 +1,53 @@
/*
* Copyright 2017-2019 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 example.seed.client.app

import cats.effect._
import cats.syntax.functor._
import example.seed.client.common.models._
import example.seed.client.process._
import example.seed.config.ConfigService
import fs2.Stream
import io.chrisdavenport.log4cats.Logger
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import pureconfig.generic.auto._

abstract class ClientBoot[F[_]: ConcurrentEffect: ContextShift] {

def avroPeopleServiceClient(host: String, port: Int)(
implicit L: Logger[F]): Stream[F, AvroPeopleServiceClient[F]] =
AvroPeopleServiceClient.createClient(host, port, sslEnabled = false)

def protoPeopleServiceClient(host: String, port: Int)(
implicit L: Logger[F]): Stream[F, ProtoPeopleServiceClient[F]] =
ProtoPeopleServiceClient.createClient(host, port, sslEnabled = false)

def runProgram(args: List[String]): Stream[F, ExitCode] = {
def setupConfig: F[SeedClientConfig] =
ConfigService[F]
.serviceConfig[ClientConfig]
.map(client => SeedClientConfig(client, ClientParams.loadParams(client.name, args)))

for {
config <- Stream.eval(setupConfig)
logger <- Stream.eval(Slf4jLogger.fromName[F](config.client.name))
exitCode <- clientProgram(config)(logger)
} yield exitCode
}

def clientProgram(config: SeedClientConfig)(implicit L: Logger[F]): Stream[F, ExitCode]
Copy link
Contributor

Choose a reason for hiding this comment

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

An alternative could make ClientBoot extends IOApp:

abstract class ClientBoot[F[_]: ConcurrentEffect: ContextShift] {

  def avroPeopleServiceClient(host: String, port: Int)(
      implicit L: Logger[F]): Stream[F, AvroPeopleServiceClient[F]] =
    AvroPeopleServiceClient.createClient(host, port, sslEnabled = false)

  def protoPeopleServiceClient(host: String, port: Int)(
      implicit L: Logger[F]): Stream[F, ProtoPeopleServiceClient[F]] =
    ProtoPeopleServiceClient.createClient(host, port, sslEnabled = false)

  def clientProgram(config: SeedClientConfig)(implicit L: Logger[F]): Stream[F, ExitCode]

  def run(args: List[String]): IO[ExitCode] = {
    def setupConfig: F[SeedClientConfig] =
      ConfigService[F]
        .serviceConfig[ClientConfig]
        .map(client => SeedClientConfig(client, ClientParams.loadParams(client.name, args)))

    (for {
      config   <- Stream.eval(setupConfig)
      logger   <- Stream.eval(Slf4jLogger.fromName[F](config.client.name))
      exitCode <- clientProgram(config)(logger)
    } yield exitCode).compile.toList.map(_.headOption.getOrElse(ExitCode.Error))
  }
}

So, the mains apps just need to:

class AvroClientProgram[F[_]: ConcurrentEffect: ContextShift] extends ClientBoot[F] {

  def clientProgram(config: SeedClientConfig)(implicit L: Logger[F]): Stream[F, ExitCode] = {
    for {
      peopleClient <- avroPeopleServiceClient(config.client.host, config.client.port)
      result       <- Stream.eval(peopleClient.getPerson(config.params.request))
    } yield result.fold(_ => ExitCode.Error, _ => ExitCode.Success)
  }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To do this I will need an F on each method because the run method will need to have everything on IO, I prefer to leave it at it is but I can change to that if you want

}
@@ -0,0 +1,39 @@
/*
* Copyright 2017-2019 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 example.seed.client.app

import example.seed.client.common.models.ParamsConfig
import scopt.OptionParser

object ClientParams {

val default = ParamsConfig("Foo")

def paramsConfig(name: String): OptionParser[ParamsConfig] =
new scopt.OptionParser[ParamsConfig](name) {

opt[String]("name")
.required()
.action((value, config) => config.copy(request = value))
.text("The name for the request")

}

def loadParams(name: String, args: List[String]): ParamsConfig =
paramsConfig(name).parse(args, default).getOrElse(default)

}