Skip to content

Commit

Permalink
small refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
victornguen committed Oct 13, 2022
1 parent 850f94c commit 2764487
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 13 deletions.
2 changes: 1 addition & 1 deletion mainservice/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ lazy val Versions = new {
val http4s = "0.23.12"
val zio = "2.0.2"
val zhttp = "2.0.0-RC10"
val zioJson = "0.3.0"
val zioJson = "0.3.0-RC10"
val zioInteropCats = "3.3.0"
val circe = "0.14.3"
val scalaTest = "3.0.8"
Expand Down
3 changes: 2 additions & 1 deletion mainservice/src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ app {

services {
dataExtractor = "http://openscoring-data-extractor:8280"
recommendationService = "http://openscoring-recomendation-service:8999"
recommendationService = "http://openscoring-recomendation-system:8999"
// recommendationService = "http://localhost:8999"
}
37 changes: 27 additions & 10 deletions mainservice/src/main/scala/com/scalalazy/mainservice/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ package com.scalalazy.mainservice

import cats.effect.ExitCode
import cats.effect.unsafe.implicits.global
import com.scalalazy.mainservice.Main.creditApplicationResultRoute
import com.scalalazy.mainservice.model.config.{Application, TSConfigLoader}
import com.scalalazy.mainservice.module.CreditApplicationDB.{CreditApplicationRepository, InMemoryCreditApplicationRepository}
import com.scalalazy.mainservice.module.CreditApplicationDB.{
CreditApplicationRepository,
InMemoryCreditApplicationRepository
}
import com.scalalazy.mainservice.module.PersonDB.{InMemoryPersonRepository, PersonRepository}
import com.scalalazy.mainservice.module.UserDB.{InMemoryUserRepository, UserRepository}
import com.scalalazy.mainservice.module.logger.{Logger => MyLogger}
import com.scalalazy.mainservice.route.{CreditApplicationRoute, UserRoute}
import com.scalalazy.mainservice.route.{CreditApplicationResultRoutes, CreditApplicationRoute, UserRoute}
import com.typesafe.config.ConfigFactory
import eu.timepit.refined.auto._
import io.getquill.{PostgresJdbcContext, SnakeCase}
Expand All @@ -21,25 +25,35 @@ import sttp.tapir.server.ziohttp.ZioHttpInterpreter
import sttp.tapir.swagger.SwaggerUI
import sttp.tapir.swagger.bundle.SwaggerInterpreter
import zhttp.http.{Http, Request, Response}
import zhttp.service.{ChannelFactory, EventLoopGroup}

import scala.jdk.CollectionConverters._
import scala.util.Try

object Main extends CatsApp {
import cats.effect.unsafe.implicits.global
type AppEnvironment = UserRepository with MyLogger with PersonRepository with CreditApplicationRepository
type AppEnvironment = UserRepository
with MyLogger with PersonRepository with CreditApplicationRepository with ChannelFactory
with CreditApplicationRepository with EventLoopGroup

private val userRoute = new UserRoute[AppEnvironment]
private val creditApplicationRoute = new CreditApplicationRoute[AppEnvironment]
private val creditApplicationResultRoute = new CreditApplicationResultRoutes[AppEnvironment]
// private val personRoute = new PersonRoute[AppEnvironment]

lazy val openAPIDoc: OpenAPI = OpenAPIDocsInterpreter()
.toOpenAPI(userRoute.getEndPoints ++ creditApplicationRoute.getEndPoints, "OpenScoring", "0.1.0")
.toOpenAPI(
userRoute.getEndPoints ++ creditApplicationRoute.getEndPoints ++ creditApplicationResultRoute.getEndpoints,
"OpenScoring",
"0.1.0")

val swaggerFromOpenApi: Http[Any, Throwable, Request, Response] =
ZioHttpInterpreter().toHttp(SwaggerUI[Task](openAPIDoc.toYaml))

private val httpApp = userRoute.getRoutes ++ creditApplicationRoute.getRoutes ++ swaggerFromOpenApi
private val httpApp = userRoute.getRoutes ++
creditApplicationRoute.getRoutes ++
creditApplicationResultRoute.getRoutes ++
swaggerFromOpenApi

// override def run = for{
// conf <- config
Expand All @@ -53,11 +67,14 @@ object Main extends CatsApp {
// } yield result

def run = app.provide(
InMemoryUserRepository.layer,
InMemoryCreditApplicationRepository.layer,
InMemoryPersonRepository.layer,
module.logger.Logger.layer
)
InMemoryUserRepository.layer,
InMemoryCreditApplicationRepository.layer,
InMemoryPersonRepository.layer,
module.logger.Logger.layer,
Scope.default,
EventLoopGroup.default,
ChannelFactory.auto
)

val config: ZIO[Any, Throwable, Application] = for {
applicationConfigIO <- ZIO.fromTry(Try(Application.getConfig.load[cats.effect.IO]))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ package com.scalalazy.mainservice.model
sealed abstract class ExpectedFailure extends Exception
case class DBFailure(throwable: Throwable) extends ExpectedFailure
case class NotFoundFailure(message: String) extends ExpectedFailure

case class ConfigError(message: String = "") extends ExpectedFailure
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.scalalazy.mainservice.model.dto
import zio.json.JsonCodec

case class CreateCreditRequestDTO (amount: BigDecimal,
timeLimitMonth: Month,
accountBalance: BigDecimal,
monthIncome: BigDecimal)

case class Month(value: Double) extends AnyVal

object CreateCreditRequestDTO{
implicit val codec: JsonCodec[CreateCreditRequestDTO] = zio.json.DeriveJsonCodec.gen[CreateCreditRequestDTO]
}

object Month{
implicit val codec: JsonCodec[Month] = zio.json.DeriveJsonCodec.gen[Month]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.scalalazy.mainservice.model.dto

import zio.json.{DeriveJsonCodec, DeriveJsonDecoder, DeriveJsonEncoder, JsonCodec, JsonDecoder, JsonEncoder}


/** Кредитный тариф состоит из:
* - нижней и верхней границ получаемой суммы
* - кредитной ставки
* - нижней и верхней границы получения кредита
*/

case class CreditApplicationResultDTO(amountLowerBound: BigDecimal, amountUpperBound: BigDecimal, percentage: Double, timeLimitMonthLower: Month, timeLimitMonthUpper: Month)

object CreditApplicationResultDTO {
// implicit val codec: JsonCodec[CreditApplicationResultDTO] = DeriveJsonCodec.gen[CreditApplicationResultDTO]

implicit val decoder = DeriveJsonDecoder.gen[CreditApplicationResultDTO]
implicit val encoder = DeriveJsonEncoder.gen[CreditApplicationResultDTO]
// implicit val decoder = JsonDecoder[List[Json]].map(list => list.map(ca => CreditApplicationResultDTO(ca)))
}

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ object CreditApplicationRepository {
def layer(ctx: PostgresJdbcContext[SnakeCase.type]): ULayer[LiveCreditApplicationRepository] =
ZLayer.succeed(new LiveCreditApplicationRepository(ctx))

def get(id: String): ZIO[Service, ExpectedFailure, Option[CreditApplication]] = ZIO.serviceWithZIO[CreditApplicationRepository.Service](_.get(id))

trait Service {
def get(id: String): ZIO[Any, ExpectedFailure, Option[CreditApplication]]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.scalalazy.mainservice.route
import com.scalalazy.mainservice.helpers.{RouteHelper, ServerOptionsHelper}
import com.scalalazy.mainservice.model.{ConfigError, ExpectedFailure, NotFoundFailure}
import com.scalalazy.mainservice.model.dto.{CreateCreditApplicationDTO, CreateCreditRequestDTO, CreditApplicationResultDTO, Month}
import com.scalalazy.mainservice.model.dto.response.CreditApplicationCreatedDTO
import com.scalalazy.mainservice.model.response.{ErrorResponse, InternalServerErrorResponse, NotFoundResponse}
import com.scalalazy.mainservice.module.CreditApplicationDB
import com.scalalazy.mainservice.module.CreditApplicationDB.CreditApplicationRepository
import com.scalalazy.mainservice.module.PersonDB.PersonRepository
import com.scalalazy.mainservice.module.logger.{Logger, debug}
import com.typesafe.config.ConfigFactory
import org.http4s.dsl.Http4sDsl
import sttp.model.StatusCode
import sttp.tapir.ztapir.{endpoint, oneOf, oneOfVariant, statusCode, _}
import zio.RIO
import sttp.tapir.generic.auto._
import io.circe.generic.auto._
import sttp.tapir.json.circe.jsonBody
import sttp.tapir.server.ziohttp.ZioHttpInterpreter
import zhttp.http.{Http, HttpData, Method, Request, Response}
import zhttp.service.{ChannelFactory, Client, EventLoopGroup}
import zio.json.{DecoderOps, EncoderOps}
import zio.{RIO, ZIO}

class CreditApplicationResultRoutes[R <: Logger with EventLoopGroup with ChannelFactory with CreditApplicationRepository] extends Http4sDsl[RIO[R, *]] with RouteHelper[R] with ServerOptionsHelper[R] {

private val getCreditApplicationResultEndPoint = endpoint.get
.description("Get credit application result")
.in("creditapplication" / "result" / path[String].description("credit application ID"))
.errorOut(
oneOf[ErrorResponse](
oneOfVariant(statusCode(StatusCode.InternalServerError) and jsonBody[InternalServerErrorResponse]
.description("Internal server error")),
oneOfVariant(statusCode(StatusCode.NotFound) and jsonBody[NotFoundResponse].description("Not Found"))
)
)
.out(jsonBody[List[CreditApplicationResultDTO]])

val getRoutes = ZioHttpInterpreter().toHttp(
List(
getCreditApplicationResultEndPoint.zServerLogic { applicationId =>
handleError(getResultForCreditApplication(applicationId))
}
))

def getResultForCreditApplication(applicationId: String) =
for {
creditApplication <- CreditApplicationDB.get(applicationId)
hostConf <- ZIO.from(ConfigFactory.load.getString("services.recommendationService")).mapError(e => ConfigError(e.toString))
// ca <- ZIO.fromOption(creditApplication).mapError(e => NotFoundFailure(s"not found application : $applicationId"))
request = CreateCreditRequestDTO(
amount = BigDecimal(creditApplication.map(_.sum).getOrElse(10000L)),
timeLimitMonth = Month(creditApplication.map(_.periodInMonth.toDouble).getOrElse(3.0)),
accountBalance = BigDecimal(1000),
monthIncome = BigDecimal(100))
response <- Client.request(
"http://localhost:8999/decision",
Method.POST,
content = HttpData.fromCharSequence(request.toJson)).mapError(e => NotFoundFailure(""))

json <- response.bodyAsString.map(_.fromJson[List[CreditApplicationResultDTO]]).mapError(e => NotFoundFailure(s"can't parse response"))
result <- json match {
case Left(value) => ZIO.fail(NotFoundFailure(s"can't parse response: $value"))
case Right(value) => ZIO.succeed(value)
}
} yield result

def getEndpoints = List(getCreditApplicationResultEndPoint)
}
6 changes: 6 additions & 0 deletions recomendationSystem/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,9 @@ lazy val root = (project in file("."))
),
testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework")
)

enablePlugins(JavaAppPackaging)
enablePlugins(DockerPlugin)

Docker / packageName := "openscoring-recomendation-system"
Docker / dockerExposedPorts := Seq(8999)
1 change: 1 addition & 0 deletions recomendationSystem/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.9")
2 changes: 1 addition & 1 deletion recomendationSystem/src/main/scala/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import zio._

object Main extends ZIOAppDefault {
override def run: ZIO[Any with ZIOAppArgs with Scope, Any, Any] = Server
.start(8080, Routes.rulesRoutes ++ Routes.rateRoutes ++ Routes.creditRequestRoutes)
.start(8999, Routes.rulesRoutes ++ Routes.rateRoutes ++ Routes.creditRequestRoutes)
.provide(InMemoryCreditRateStorage.live, InMemoryCreditRulesStorage.live, InMemoryCreditRequestsStorage.live)

}
2 changes: 2 additions & 0 deletions recomendationSystem/src/main/scala/Routes/Routes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ object Routes {
} yield r
case req @ Method.POST -> !! / "decision" => for {
body <- req.bodyAsString.map(_.fromJson[CreditRequest])
_ <- zio.Console.printLine(body)
r <- body match {
case Left(value) => ZIO
.log(s"Failed to parse the input: $value")
Expand All @@ -50,6 +51,7 @@ object Routes {
)
case Right(value) => CreditRequestStorage.makeDecision(value).map(list => Response.json(list.toJson))
}
_ <- zio.Console.printLine(r.data.toString)
} yield r
}

Expand Down

0 comments on commit 2764487

Please sign in to comment.