/ingest/src/main/scala/hydra.ingest/app/Main.scala

https://github.com/pluralsight/hydra · Scala · 110 lines · 96 code · 12 blank · 2 comment · 5 complexity · b10089021515fd94b63e664cc8f617d4 MD5 · raw file

  1. package hydra.ingest.app
  2. import akka.actor.{Actor, ActorSystem, Props}
  3. import akka.http.scaladsl.Http
  4. import akka.http.scaladsl.Http.ServerBinding
  5. import akka.http.scaladsl.server.Route
  6. import cats.effect.{ExitCode, IO, IOApp, Resource}
  7. import hydra.common.Settings
  8. import hydra.common.config.ConfigSupport
  9. import ConfigSupport._
  10. import hydra.common.logging.LoggingAdapter
  11. import hydra.core.http.CorsSupport
  12. import hydra.ingest.bootstrap.ActorFactory
  13. import hydra.ingest.modules.{Algebras, Bootstrap, Programs, Routes}
  14. import io.chrisdavenport.log4cats.SelfAwareStructuredLogger
  15. import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
  16. import kamon.Kamon
  17. import kamon.prometheus.PrometheusReporter
  18. import scala.concurrent.ExecutionContext.Implicits.global
  19. // $COVERAGE-OFF$Disabling highlighting by default until a workaround for https://issues.scala-lang.org/browse/SI-8596 is found
  20. object Main extends IOApp with ConfigSupport with LoggingAdapter {
  21. private implicit val catsLogger: SelfAwareStructuredLogger[IO] =
  22. Slf4jLogger.getLogger[IO]
  23. private def getActorSystem: Resource[IO, ActorSystem] = {
  24. val registerCoordinatedShutdown: ActorSystem => IO[Unit] = system =>
  25. IO(system.terminate())
  26. val system = IO(ActorSystem("hydra", rootConfig))
  27. Resource.make(system)(registerCoordinatedShutdown)
  28. }
  29. private def report =
  30. IO({
  31. val enablePrometheus = applicationConfig
  32. .getBooleanOpt("monitoring.prometheus.enable")
  33. .getOrElse(false)
  34. if (enablePrometheus) {
  35. val module = new PrometheusReporter()
  36. Kamon.registerModule("MainModule", module)
  37. }
  38. })
  39. private def actorsIO()(implicit system: ActorSystem): IO[Unit] = {
  40. IO {
  41. class Service extends Actor {
  42. override def preStart(): Unit = {
  43. ActorFactory.getActors().foreach {
  44. case (name, props) =>
  45. context.actorOf(props, name)
  46. }
  47. }
  48. override def receive: Receive = {
  49. case _ => ()
  50. }
  51. }
  52. system.actorOf(Props[Service], "service")
  53. }
  54. }
  55. private def serverIO(routes: Routes[IO], settings: Settings)(
  56. implicit system: ActorSystem
  57. ): IO[ServerBinding] =
  58. for {
  59. r <- routes.routes
  60. server <- IO.fromFuture(
  61. IO(
  62. Http().bindAndHandle(r, settings.httpInterface, settings.httpPort)
  63. )
  64. )
  65. } yield server
  66. private def buildProgram()(implicit system: ActorSystem): IO[Unit] = {
  67. import scalacache.Mode
  68. implicit val mode: Mode[IO] = scalacache.CatsEffect.modes.async
  69. AppConfig.appConfig.load[IO].flatMap { config => {
  70. implicit val cors = new CorsSupport(config.corsAllowedOriginConfig.corsAllowedOrigins)
  71. for {
  72. algebras <- Algebras
  73. .make[IO](config)
  74. programs <- Programs.make[IO](config, algebras)
  75. bootstrap <- Bootstrap
  76. .make[IO](programs.createTopic, config.metadataTopicsConfig,
  77. config.dvsConsumersTopicConfig, config.consumerOffsetsOffsetsTopicConfig, algebras.kafkaAdmin, config.tagsConfig)
  78. _ <- actorsIO()
  79. _ <- bootstrap.bootstrapAll
  80. routes <- Routes.make[IO](programs, algebras, config)
  81. _ <- report
  82. _ <- serverIO(routes, Settings.HydraSettings)
  83. _ <- if (config.consumerGroupsAlgebraConfig.consumerGroupsConsumerEnabled) {
  84. algebras.consumerGroups.startConsumer
  85. } else {
  86. IO.unit
  87. }
  88. } yield ()
  89. }
  90. }
  91. }
  92. override def run(args: List[String]): IO[ExitCode] = {
  93. getActorSystem.use { implicit system =>
  94. buildProgram() *> IO.never.map(_ => ExitCode.Success)
  95. }
  96. }
  97. }
  98. // $COVERAGE-ON