aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/com/drivergrp/core/app.scala
diff options
context:
space:
mode:
authorvlad <vlad@drivergrp.com>2016-07-16 15:55:19 -0400
committervlad <vlad@drivergrp.com>2016-07-16 15:55:19 -0400
commitc948b1f2c1c7a5246d5c1a7cba05e6e27a9d7b57 (patch)
tree8737b3bc5e49c287173f52ca936d36fceb86b4d0 /src/main/scala/com/drivergrp/core/app.scala
parent482459a63433c281b7a576236111e6a86e4521c9 (diff)
downloaddriver-core-c948b1f2c1c7a5246d5c1a7cba05e6e27a9d7b57.tar.gz
driver-core-c948b1f2c1c7a5246d5c1a7cba05e6e27a9d7b57.tar.bz2
driver-core-c948b1f2c1c7a5246d5c1a7cba05e6e27a9d7b57.zip
Modules consolidation
Diffstat (limited to 'src/main/scala/com/drivergrp/core/app.scala')
-rw-r--r--src/main/scala/com/drivergrp/core/app.scala115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/main/scala/com/drivergrp/core/app.scala b/src/main/scala/com/drivergrp/core/app.scala
new file mode 100644
index 0000000..34a92e3
--- /dev/null
+++ b/src/main/scala/com/drivergrp/core/app.scala
@@ -0,0 +1,115 @@
+package com.drivergrp.core
+
+import akka.actor.ActorSystem
+import akka.http.scaladsl.Http
+import akka.http.scaladsl.server.Directives._
+import akka.http.scaladsl.server.RouteResult._
+import akka.stream.ActorMaterializer
+import com.drivergrp.core.logging.{Logger, TypesafeScalaLogger}
+import akka.http.scaladsl.server.{Route, RouteConcatenation}
+import com.drivergrp.core.rest.Swagger
+import com.typesafe.config.Config
+import org.slf4j.LoggerFactory
+
+
+object app {
+
+ class DriverApp(modules: Seq[Module],
+ log: Logger = new TypesafeScalaLogger(
+ com.typesafe.scalalogging.Logger(LoggerFactory.getLogger(classOf[DriverApp]))),
+ config: Config = com.drivergrp.core.config.loadDefaultConfig,
+ interface: String = "localhost", port: Int = 8080) {
+
+ def run() = {
+ activateServices(modules)
+ scheduleServicesDeactivation(modules)
+ bindHttp(modules)
+ }
+
+ protected def bindHttp(modules: Seq[Module]) {
+ implicit val actorSystem = ActorSystem("spray-routing", config)
+ implicit val executionContext = actorSystem.dispatcher
+ implicit val materializer = ActorMaterializer()(actorSystem)
+
+ val serviceTypes = modules.flatMap(_.routeTypes)
+ val swaggerService = new Swagger(actorSystem, serviceTypes, config)
+ val swaggerRoutes = swaggerService.routes ~ swaggerService.swaggerUI
+
+ Http()(actorSystem).bindAndHandle(
+ route2HandlerFlow(logRequestResult("log")(modules.map(_.route).foldLeft(swaggerRoutes) { _ ~ _ })),
+ interface, port)(materializer)
+ }
+
+ /**
+ * Initializes services
+ */
+ protected def activateServices(services: Seq[Module]) = {
+ services.foreach { service =>
+ Console.print(s"Service ${service.name} starts ...")
+ try {
+ service.activate()
+ } catch {
+ case t: Throwable =>
+ log.fatal(s"Service ${service.name} failed to activate", t)
+ Console.print(" Failed! (check log)")
+ }
+ Console.println(" Done")
+ }
+ }
+
+ /**
+ * Schedules services to be deactivated on the app shutdown
+ */
+ protected def scheduleServicesDeactivation(services: Seq[Module]) = {
+ Runtime.getRuntime.addShutdownHook(new Thread() {
+ override def run(): Unit = {
+ services.foreach { service =>
+ Console.print(s"Service ${service.name} shutting down ...")
+ try {
+ service.deactivate()
+ } catch {
+ case t: Throwable =>
+ log.fatal(s"Service ${service.name} failed to deactivate", t)
+ Console.print(" Failed! (check log)")
+ }
+ Console.println(" Done")
+ }
+ }
+ })
+ }
+ }
+
+
+ import scala.reflect.runtime.universe._
+
+ trait Module {
+ val name: String
+ def route: Route
+ def routeTypes: Seq[Type]
+
+ def activate(): Unit = {}
+ def deactivate(): Unit = {}
+ }
+
+ class SimpleModule(val name: String, val route: Route, routeType: Type) extends Module {
+ def routeTypes: Seq[Type] = Seq(routeType)
+ }
+
+ /**
+ * Module implementation which may be used to composed a few
+ *
+ * @param name more general name of the composite module,
+ * must be provided as there is no good way to automatically
+ * generalize the name from the composed modules' names
+ * @param modules modules to compose into a single one
+ */
+ class CompositeModule(val name: String, modules: Seq[Module])
+ extends Module with RouteConcatenation {
+
+ def route: Route = modules.map(_.route).reduce(_ ~ _)
+ def routeTypes = modules.flatMap(_.routeTypes)
+
+ override def activate() = modules.foreach(_.activate())
+ override def deactivate() = modules.reverse.foreach(_.deactivate())
+ }
+}