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

Feat: add Reaktoro integration #11

Merged
merged 8 commits into from
Nov 18, 2024
Merged
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ RUN sbt update

COPY src/ ./src/

RUN sbt compile
RUN sbt clean compile

COPY . .

Expand Down
13 changes: 11 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Test / scalaSource := baseDirectory.value / "src" / "test" / "scala"

lazy val root = (project in file("."))
.settings(
name := "chemist-flow",
name := ".",
libraryDependencies ++= Seq(
scalaLogging,
scalaTest,
Expand All @@ -40,4 +40,13 @@ lazy val root = (project in file("."))
)
)

resolvers += "Akka library repository".at("https://repo.akka.io/maven")
scalacOptions ++= Seq(
"-Xmax-inlines", "64"
)

resolvers ++= Seq(
"Akka library repository" at "https://repo.akka.io/maven",
"Sonatype OSS Releases" at "https://oss.sonatype.org/content/repositories/releases/",
"Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/",
"Maven Central" at "https://repo1.maven.org/maven2/"
)
13 changes: 13 additions & 0 deletions examples/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
AKKA_LICENSE_KEY=...

CHEMIST_FLOW_HOST=localhost
CHEMIST_FLOW_PORT=8081

POSTGRE_URL=jdbc:postgresql://localhost:5432/chemist_db
POSTGRE_USER=chemist
POSTGRE_PASSWORD=chemist_password
POSTGRE_DRIVER=org.postgresql.Driver

CHEMIST_PREPROCESSOR_BASE_URI=http://localhost:8080

CHEMIST_ENGINE_BASE_URI=http://localhost:8082
9 changes: 8 additions & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0")
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.10.4")
addSbtPlugin("org.http4s" % "sbt-http4s-org" % "0.17.5")
resolvers += "Scalafmt Releases" at "https://oss.sonatype.org/content/repositories/releases"

resolvers ++= Seq(
"Scalafmt Releases" at "https://oss.sonatype.org/content/repositories/releases",
"Sonatype OSS Releases" at "https://oss.sonatype.org/content/repositories/releases",
"Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/",
"Maven Central" at "https://repo1.maven.org/maven2/",
"Akka repository" at "https://repo.akka.io/maven"
)
49 changes: 0 additions & 49 deletions src/main/scala/api/Endpoints.scala

This file was deleted.

7 changes: 5 additions & 2 deletions src/main/scala/api/ServerBuilder.scala
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package api

import cats.effect.{IO, Resource}

import com.comcast.ip4s.{Host, Port}

import org.http4s.server.Server
import org.http4s.ember.server.EmberServerBuilder
import org.http4s.HttpRoutes

class ServerBuilder(
implicit endpoints: Endpoints
routes: HttpRoutes[IO]
) {

def startServer(
Expand All @@ -17,7 +20,7 @@ class ServerBuilder(
.default[IO]
.withHost(host)
.withPort(port)
.withHttpApp(ErrorHandler(endpoints.routes).orNotFound)
.withHttpApp(ErrorHandler(routes).orNotFound)
.build
}

Expand Down
54 changes: 54 additions & 0 deletions src/main/scala/api/endpoints/flow/ReaktoroEndpoints.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package api.endpoints.flow

import cats.effect.IO

import org.http4s.HttpRoutes
import org.http4s.dsl.io._
import org.http4s.server.Router
import org.http4s.server.middleware.Logger
import org.http4s.circe.CirceEntityEncoder.circeEntityEncoder
import org.http4s.circe.CirceSensitiveDataEntityDecoder.circeEntityDecoder

import io.circe.syntax._
import io.circe.generic.auto.deriveEncoder

import core.services.flow.ReaktoroService
import core.domain.preprocessor.ReactionId
import core.domain.flow.{DataBase, MoleculeAmountList}

case class ComputePropsRequest(
reactionId: ReactionId,
database: DataBase,
amounts: MoleculeAmountList
)

object ComputePropsRequest {
import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}

implicit val decoder: Decoder[ComputePropsRequest] = deriveDecoder
implicit val encoder: Encoder[ComputePropsRequest] = deriveEncoder
}

class ReaktoroEndpoints(
reaktoroService: ReaktoroService[IO]
) {

private val computeSystemPropsForReactionRoute: HttpRoutes[IO] = HttpRoutes.of[IO] {
case req @ POST -> Root / "system" / "properties" =>
req.as[ComputePropsRequest].flatMap {
case ComputePropsRequest(reactionId, database, amounts) =>
reaktoroService
.computeSystemPropsForReaction(reactionId, database, amounts)
.flatMap(result => Ok(result.asJson))
.handleErrorWith(ex => InternalServerError(("InternalError", ex.getMessage).asJson))
}
}

val routes: HttpRoutes[IO] = Logger.httpRoutes(logHeaders = true, logBody = true)(
Router(
"/api" -> computeSystemPropsForReactionRoute
)
)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package api.endpoints.preprocessor

import cats.effect.IO
import cats.syntax.semigroupk.toSemigroupKOps

import io.circe.syntax.EncoderOps

import org.http4s.HttpRoutes
import org.http4s.dsl.io._
import org.http4s.server.Router
import org.http4s.server.middleware.Logger
import org.http4s.circe.CirceEntityEncoder.circeEntityEncoder
import org.http4s.circe.CirceSensitiveDataEntityDecoder.circeEntityDecoder

import core.services.preprocessor.{MechanismService, ReactionService}
import core.domain.preprocessor.{MechanismDetails, Reaction, ReactionDetails}
import core.errors.http.preprocessor.ReactionError

class PreprocessorEndpoints(
reactionService: ReactionService[IO],
mechanismService: MechanismService[IO]
) {

private val getReactionRoute: HttpRoutes[IO] = HttpRoutes.of[IO] {
case GET -> Root / "reaction" / id =>
validateId(id) match {
case Some(validId) =>
reactionService.getReaction(validId).flatMap {
(reactionDetails: ReactionDetails) => Ok(reactionDetails.asJson)
}.handleErrorWith {
case _: ReactionError.NotFoundError => NotFound(("NotFound", s"Reaction with ID $validId not found"))
case ex => InternalServerError(("InternalError", ex.getMessage))
}
case None => BadRequest(("BadRequest", "ID must be an integer"))
}
}

private val postReactionRoute: HttpRoutes[IO] = HttpRoutes.of[IO] {
case req @ POST -> Root / "reaction" =>
req.as[Reaction].flatMap { reaction =>
reactionService.createReaction(reaction).flatMap {
createdReaction => Created(createdReaction.asJson)
}.handleErrorWith {
case _: ReactionError.CreationError => BadRequest(("CreationError", "Failed to create reaction"))
case ex => InternalServerError(("InternalError", ex.getMessage))
}
}
}

private val deleteReactionRoute: HttpRoutes[IO] = HttpRoutes.of[IO] {
case DELETE -> Root / "reaction" / id =>
validateId(id) match {
case Some(validId) =>
reactionService.deleteReaction(validId).flatMap {
case Right(_) => NoContent()
case Left(error) => BadRequest(("DeletionError", error.message))
}
case None => BadRequest(("BadRequest", "ID must be an integer"))
}
}

private val getMechanismRoute: HttpRoutes[IO] = HttpRoutes.of[IO] {
case GET -> Root / "mechanism" / id =>
validateId(id) match {
case Some(validId) =>
mechanismService.getMechanism(validId).flatMap {
(mechanismDetails: MechanismDetails) => Ok(mechanismDetails.asJson)
}.handleErrorWith {
case _: ReactionError.NotFoundError => NotFound(("NotFound", s"Mechanism with ID $validId not found"))
case ex => InternalServerError(("InternalError", ex.getMessage))
}
case None => BadRequest(("BadRequest", "ID must be an integer"))
}
}

private def validateId(id: String): Option[Int] = id.toIntOption

val routes: HttpRoutes[IO] = Logger.httpRoutes(logHeaders = false, logBody = true)(
Router(
"/api" -> (getReactionRoute <+> postReactionRoute <+> deleteReactionRoute <+> getMechanismRoute)
)
)

}
Loading
Loading