aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/byspel/app
diff options
context:
space:
mode:
authorJakob Odersky <jakob@odersky.com>2018-10-27 18:45:06 -0700
committerJakob Odersky <jakob@odersky.com>2018-10-27 18:45:06 -0700
commitde095d377859887352c7380e52ea89bcabf662a0 (patch)
tree6cee6eb17c1977b85e01078e926499b33854047d /src/main/scala/byspel/app
downloadbyspel-de095d377859887352c7380e52ea89bcabf662a0.tar.gz
byspel-de095d377859887352c7380e52ea89bcabf662a0.tar.bz2
byspel-de095d377859887352c7380e52ea89bcabf662a0.zip
Initial commit
Diffstat (limited to 'src/main/scala/byspel/app')
-rw-r--r--src/main/scala/byspel/app/App.scala57
-rw-r--r--src/main/scala/byspel/app/config.scala16
-rw-r--r--src/main/scala/byspel/app/modules.scala51
3 files changed, 124 insertions, 0 deletions
diff --git a/src/main/scala/byspel/app/App.scala b/src/main/scala/byspel/app/App.scala
new file mode 100644
index 0000000..65b3c3f
--- /dev/null
+++ b/src/main/scala/byspel/app/App.scala
@@ -0,0 +1,57 @@
+package byspel
+package app
+
+import akka.actor.ActorSystem
+import akka.stream.{ActorMaterializer, Materializer}
+import java.nio.file.{Files, Paths}
+import scala.concurrent.ExecutionContext
+import toml.Toml
+
+trait App {
+
+ implicit lazy val system: ActorSystem = ActorSystem()
+
+ implicit lazy val materializer: Materializer = ActorMaterializer()
+
+ implicit lazy val executionContext: ExecutionContext = system.dispatcher
+
+ def start(): Unit = {}
+ def stop(): Unit = {}
+
+ def log(msg: String) = System.err.println(msg)
+
+ private var _args: List[String] = Nil
+ def args = _args
+
+ lazy val config = args match {
+ case Nil =>
+ log("fatal: no config file given as first argument")
+ sys.exit(1)
+ case head :: _ if Files.isReadable(Paths.get(head)) =>
+ log(s"loading config from '${args(0)}'")
+ import toml.Codecs._
+ Toml.parseAs[Config](Files.readString(Paths.get(head))) match {
+ case Left(err) =>
+ log(s"fatal: syntax error in config file: $err")
+ sys.exit(1)
+ case Right(value) => value
+ }
+ case head :: _ =>
+ log(s"fatal: config file '$head' is not readable or does not exist")
+ sys.exit(1)
+ }
+
+ def main(args: Array[String]): Unit = {
+ log("starting application")
+ _args = args.toList
+ config
+ sys.addShutdownHook {
+ log("stopping application")
+ stop()
+ log("bye")
+ }
+ start()
+ log("ready")
+ }
+
+}
diff --git a/src/main/scala/byspel/app/config.scala b/src/main/scala/byspel/app/config.scala
new file mode 100644
index 0000000..6ba9f80
--- /dev/null
+++ b/src/main/scala/byspel/app/config.scala
@@ -0,0 +1,16 @@
+package byspel
+package app
+
+case class Config(
+ http: HttpConfig,
+ database: DatabaseConfig
+)
+
+case class HttpConfig(
+ address: String,
+ port: Int
+)
+case class DatabaseConfig(
+ file: String,
+ sqitch_base: String
+)
diff --git a/src/main/scala/byspel/app/modules.scala b/src/main/scala/byspel/app/modules.scala
new file mode 100644
index 0000000..a4b85ae
--- /dev/null
+++ b/src/main/scala/byspel/app/modules.scala
@@ -0,0 +1,51 @@
+package byspel
+package app
+
+import akka.http.scaladsl.Http
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
+import akka.http.scaladsl.server.{Directives, Route}
+import spray.json.DefaultJsonProtocol
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+trait HttpApi
+ extends Directives
+ with SprayJsonSupport
+ with DefaultJsonProtocol {
+ def route: Route
+}
+
+trait HttpApp extends App { self: HttpApi =>
+
+ override def start() = {
+ super.start()
+ log("binding to interface")
+ val future =
+ Http().bindAndHandle(route, config.http.address, config.http.port)
+ Await.result(future, 2.seconds)
+ }
+
+}
+
+trait DatabaseApi extends Tables {
+ val profile = Tables.profile
+ import profile.api._
+
+ def database: Database
+
+}
+
+trait DatabaseApp extends App { self: DatabaseApi =>
+ import profile.api.Database
+
+ lazy val database: Database = Database.forURL(
+ s"jdbc:sqlite:${config.database.file}",
+ driver = "org.sqlite.JDBC"
+ )
+
+ override def start() = {
+ super.start()
+ log("initializing database")
+ database
+ }
+}