diff options
Diffstat (limited to 'src/main/scala/xyz/driver/core/init/AkkaBootable.scala')
-rw-r--r-- | src/main/scala/xyz/driver/core/init/AkkaBootable.scala | 190 |
1 files changed, 0 insertions, 190 deletions
diff --git a/src/main/scala/xyz/driver/core/init/AkkaBootable.scala b/src/main/scala/xyz/driver/core/init/AkkaBootable.scala deleted file mode 100644 index df6611e..0000000 --- a/src/main/scala/xyz/driver/core/init/AkkaBootable.scala +++ /dev/null @@ -1,190 +0,0 @@ -package xyz.driver.core -package init - -import akka.actor.ActorSystem -import akka.http.scaladsl.Http -import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.{RequestContext, Route} -import akka.stream.scaladsl.Source -import akka.stream.{ActorMaterializer, Materializer} -import akka.util.ByteString -import com.softwaremill.sttp.SttpBackend -import com.softwaremill.sttp.akkahttp.AkkaHttpBackend -import com.typesafe.config.Config -import kamon.Kamon -import kamon.statsd.StatsDReporter -import kamon.system.SystemMetrics -import xyz.driver.core.reporting.{NoTraceReporter, Reporter, ScalaLoggingCompat, SpanContext} -import xyz.driver.core.rest.HttpRestServiceTransport - -import scala.concurrent.duration._ -import scala.concurrent.{Await, ExecutionContext, Future} - -/** Provides standard scaffolding for applications that use Akka HTTP. - * - * Among the features provided are: - * - * - execution contexts of various kinds - * - basic JVM metrics collection via Kamon - * - startup and shutdown hooks - * - * This trait provides a minimal, runnable application. It is designed to be extended by various mixins (see - * Known Subclasses) in this package. - * - * By implementing a "main" method, mixing this trait into a singleton object will result in a runnable - * application. - * I.e. - * {{{ - * object Main extends AkkaBootable // this is a runnable application - * }}} - * In case this trait isn't mixed into a top-level singleton object, the [[AkkaBootable#main main]] method should - * be called explicitly, in order to initialize and start this application. - * I.e. - * {{{ - * object Main { - * val bootable = new AkkaBootable {} - * def main(args: Array[String]): Unit = { - * bootable.main(args) - * } - * } - * }}} - * - * @groupname config Configuration - * @groupname contexts Contexts - * @groupname utilities Utilities - * @groupname hooks Overrideable Hooks - */ -trait AkkaBootable { - - /** The application's name. This value is extracted from the build configuration. - * @group config - */ - def name: String = BuildInfoReflection.name - - /** The application's version (or git sha). This value is extracted from the build configuration. - * @group config - */ - def version: Option[String] = BuildInfoReflection.version - - /** TCP port that this application will listen on. - * @group config - */ - def port: Int = 8080 - - // contexts - /** General-purpose actor system for this application. - * @group contexts - */ - implicit lazy val system: ActorSystem = ActorSystem(name) - - /** General-purpose stream materializer for this application. - * @group contexts - */ - implicit lazy val materializer: Materializer = ActorMaterializer() - - /** General-purpose execution context for this application. - * - * Note that no thread-blocking tasks should be submitted to this context. In cases that do require blocking, - * a custom execution context should be defined and used. See - * [[https://doc.akka.io/docs/akka-http/current/handling-blocking-operations-in-akka-http-routes.html this guide]] - * on how to configure custom execution contexts in Akka. - * - * @group contexts - */ - implicit lazy val executionContext: ExecutionContext = system.dispatcher - - /** Default HTTP client, backed by this application's actor system. - * @group contexts - */ - implicit lazy val httpClient: SttpBackend[Future, Source[ByteString, Any]] = AkkaHttpBackend.usingActorSystem(system) - - /** Client RPC transport abstraction. - * @group contexts - */ - implicit lazy val clientTransport: HttpRestServiceTransport = new HttpRestServiceTransport( - applicationName = Name(name), - applicationVersion = version.getOrElse("<unknown>"), - actorSystem = system, - executionContext = executionContext, - reporter = reporter - ) - - // utilities - /** Default reporter instance. - * - * Note that this is currently defined to be a ScalaLoggerLike, so that it can be implicitly converted to a - * [[com.typesafe.scalalogging.Logger]] when necessary. This conversion is provided to ensure backwards - * compatibility with code that requires such a logger. Warning: using a logger instead of a reporter will - * not include tracing information in any messages! - * - * @group utilities - */ - def reporter: Reporter with ScalaLoggingCompat = - new Reporter with NoTraceReporter with ScalaLoggingCompat { - val logger = ScalaLoggingCompat.defaultScalaLogger(json = false) - } - - /** Top-level application configuration. - * - * TODO: should we expose some config wrapper rather than the typesafe config library? - * (Author's note: I'm a fan of TOML since it's so simple. There's already an implementation for Scala - * [[https://github.com/jvican/stoml]].) - * - * @group utilities - */ - def config: Config = system.settings.config - - /** Overridable startup hook. - * - * Invoked by [[main]] during application startup. - * - * @group hooks - */ - def startup(): Unit = () - - /** Overridable shutdown hook. - * - * Invoked on an arbitrary thread when a shutdown signal is caught. - * - * @group hooks - */ - def shutdown(): Unit = () - - /** Overridable HTTP route. - * - * Any services that present an HTTP interface should implement this method. - * - * @group hooks - * @see [[HttpApi]] - */ - def route: Route = (ctx: RequestContext) => ctx.complete(StatusCodes.NotFound) - - private def syslog(message: String)(implicit ctx: SpanContext) = reporter.info(s"application: " + message) - - /** This application's entry point. */ - def main(args: Array[String]): Unit = { - implicit val ctx = SpanContext.fresh() - syslog("initializing metrics collection") - Kamon.addReporter(new StatsDReporter()) - SystemMetrics.startCollecting() - - system.registerOnTermination { - syslog("running shutdown hooks") - shutdown() - syslog("bye!") - } - - syslog("running startup hooks") - startup() - - syslog("binding to network interface") - val binding = Await.result( - Http().bindAndHandle(route, "::", port), - 2.seconds - ) - syslog(s"listening to ${binding.localAddress}") - - syslog("startup complete") - } - -} |