From 7b7f6ce4ac945a8c3bd6bdfceb31064d5aabdda0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kapica?= Date: Sat, 22 Jun 2024 23:13:25 +0200 Subject: [PATCH 1/9] Add a .do/app.yaml configuration file --- .do/app.yaml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .do/app.yaml diff --git a/.do/app.yaml b/.do/app.yaml new file mode 100644 index 0000000..0c7110a --- /dev/null +++ b/.do/app.yaml @@ -0,0 +1,33 @@ +alerts: + - rule: DEPLOYMENT_FAILED + - rule: DOMAIN_FAILED +features: + - buildpack-stack=ubuntu-22 +ingress: + rules: + - component: + name: elevator-system-api + match: + path: + prefix: /api +jobs: + - dockerfile_path: api/Dockerfile + github: + branch: feature/4 + repo: mikolajkapica/elevator-system + instance_count: 1 + instance_size_slug: apps-s-1vcpu-0.5gb + source_dir: api +name: elevator-system +region: fra +services: + - dockerfile_path: api/Dockerfile + github: + branch: feature/4 + repo: mikolajkapica/elevator-system + http_port: 8080 + instance_count: 1 + instance_size_slug: apps-s-1vcpu-0.5gb + name: elevator-system-api + run_command: sbt run + source_dir: api \ No newline at end of file From 3ef3a8726f822a07e6b583ca59875a38fd788eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kapica?= Date: Sat, 22 Jun 2024 23:14:06 +0200 Subject: [PATCH 2/9] Fix the terminating server issue caused by closing stdin by docker --- api/docker-compose.yaml | 2 -- api/src/main/scala/Server.scala | 19 ++++++++----------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/api/docker-compose.yaml b/api/docker-compose.yaml index 4682422..1e2f616 100644 --- a/api/docker-compose.yaml +++ b/api/docker-compose.yaml @@ -8,8 +8,6 @@ services: - 8080:8080 environment: - DATABASE_URL=mongodb://db:27017 - stdin_open: true - tty: true db: image: mongo:7 ports: diff --git a/api/src/main/scala/Server.scala b/api/src/main/scala/Server.scala index 1c1a902..fcfde38 100644 --- a/api/src/main/scala/Server.scala +++ b/api/src/main/scala/Server.scala @@ -2,14 +2,16 @@ import akka.actor.typed.ActorSystem import akka.actor.typed.scaladsl.Behaviors import akka.http.scaladsl.Http -import scala.concurrent.ExecutionContextExecutor -import scala.io.StdIn +import scala.concurrent.Await +import scala.concurrent.Promise +import scala.concurrent.duration.Duration object Server { - def run(): Unit = - implicit val system: ActorSystem[Any] = ActorSystem(Behaviors.empty, "my-system") - implicit val executionContext: ExecutionContextExecutor = system.executionContext + def run() = + implicit val system = ActorSystem(Behaviors.empty, "my-system") + implicit val executionContext = system.executionContext + val keepAlive = Promise[Unit].future val host = "0.0.0.0" val port = 8080 @@ -18,13 +20,8 @@ object Server { .newServerAt(host, port) .bind(Routes.route) - println(s"Server online at http://$host:$port/\nPress RETURN to stop...") - Database.test() - StdIn.readLine() - bindingFuture - .flatMap(_.unbind()) - .onComplete(_ => system.terminate()) + Await.result(keepAlive, Duration.Inf) } From 3afd7e76c690c98c18a606ffe42a39b47c52c502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kapica?= Date: Sat, 22 Jun 2024 23:30:08 +0200 Subject: [PATCH 3/9] Change Server to a while loop to detect issues --- api/src/main/scala/Server.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/scala/Server.scala b/api/src/main/scala/Server.scala index fcfde38..1cfb59d 100644 --- a/api/src/main/scala/Server.scala +++ b/api/src/main/scala/Server.scala @@ -20,7 +20,7 @@ object Server { .newServerAt(host, port) .bind(Routes.route) - Database.test() +// Database.test() Await.result(keepAlive, Duration.Inf) From 41a7f99152258df7dd1d72ba778413d0cc2b568b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kapica?= Date: Sat, 22 Jun 2024 23:54:44 +0200 Subject: [PATCH 4/9] Change Server to a while loop to detect issues --- api/src/main/scala/Server.scala | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/api/src/main/scala/Server.scala b/api/src/main/scala/Server.scala index 1cfb59d..95b10fb 100644 --- a/api/src/main/scala/Server.scala +++ b/api/src/main/scala/Server.scala @@ -9,19 +9,23 @@ import scala.concurrent.duration.Duration object Server { def run() = - implicit val system = ActorSystem(Behaviors.empty, "my-system") - implicit val executionContext = system.executionContext - val keepAlive = Promise[Unit].future - - val host = "0.0.0.0" - val port = 8080 - - val bindingFuture = Http() - .newServerAt(host, port) - .bind(Routes.route) - + while (true) { + println("Hello, world!") + Thread.sleep(1000) + } +// implicit val system = ActorSystem(Behaviors.empty, "my-system") +// implicit val executionContext = system.executionContext +// val keepAlive = Promise[Unit].future +// +// val host = "0.0.0.0" +// val port = 8080 +// +// val bindingFuture = Http() +// .newServerAt(host, port) +// .bind(Routes.route) +// // Database.test() - - Await.result(keepAlive, Duration.Inf) +// +// Await.result(keepAlive, Duration.Inf) } From 87c6dd9229b5af38f7b69453607ea923a29142f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kapica?= Date: Sun, 23 Jun 2024 00:36:34 +0200 Subject: [PATCH 5/9] Add a health check --- api/build.sbt | 9 ++---- .../main/scala/{Routes.scala => Router.scala} | 7 ++++- api/src/main/scala/Server.scala | 30 ++++++++----------- 3 files changed, 21 insertions(+), 25 deletions(-) rename api/src/main/scala/{Routes.scala => Router.scala} (76%) diff --git a/api/build.sbt b/api/build.sbt index 811ba02..4bde5b1 100644 --- a/api/build.sbt +++ b/api/build.sbt @@ -6,19 +6,16 @@ resolvers += "Akka library repository" at "https://repo.akka.io/maven" enablePlugins(JavaAppPackaging) -val scalatestVersion = "3.2.18" val AkkaVersion = "2.9.3" -val AkkaHttpVersion = "10.6.3" -val MongoDBVersion = "5.1.0" libraryDependencies ++= { Seq( - "org.scalatest" %% "scalatest" % scalatestVersion % "test", + "org.scalatest" %% "scalatest" % "3.2.18" % "test", "com.typesafe.akka" %% "akka-actor-typed" % AkkaVersion, "com.typesafe.akka" %% "akka-stream" % AkkaVersion, - "com.typesafe.akka" %% "akka-http" % AkkaHttpVersion, + "com.typesafe.akka" %% "akka-http" % "10.6.3", "org.slf4j" % "slf4j-simple" % "2.0.13", ) } -libraryDependencies += ("org.mongodb.scala" %% "mongo-scala-driver" % MongoDBVersion).cross( +libraryDependencies += ("org.mongodb.scala" %% "mongo-scala-driver" % "5.1.0").cross( CrossVersion.for3Use2_13 ) diff --git a/api/src/main/scala/Routes.scala b/api/src/main/scala/Router.scala similarity index 76% rename from api/src/main/scala/Routes.scala rename to api/src/main/scala/Router.scala index ee863cc..2ec974f 100644 --- a/api/src/main/scala/Routes.scala +++ b/api/src/main/scala/Router.scala @@ -5,7 +5,7 @@ import akka.http.scaladsl.server.Directives.get import akka.http.scaladsl.server.Directives.path import akka.http.scaladsl.server.Route -object Routes { +object Router { val route: Route = path("hello") { @@ -13,5 +13,10 @@ object Routes { complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "

Say hello to akka-http

")) } } + path("health") { + get { + complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "

OK

")) + } + } } diff --git a/api/src/main/scala/Server.scala b/api/src/main/scala/Server.scala index 95b10fb..bd54922 100644 --- a/api/src/main/scala/Server.scala +++ b/api/src/main/scala/Server.scala @@ -9,23 +9,17 @@ import scala.concurrent.duration.Duration object Server { def run() = - while (true) { - println("Hello, world!") - Thread.sleep(1000) - } -// implicit val system = ActorSystem(Behaviors.empty, "my-system") -// implicit val executionContext = system.executionContext -// val keepAlive = Promise[Unit].future -// -// val host = "0.0.0.0" -// val port = 8080 -// -// val bindingFuture = Http() -// .newServerAt(host, port) -// .bind(Routes.route) -// -// Database.test() -// -// Await.result(keepAlive, Duration.Inf) + implicit val system = ActorSystem(Behaviors.empty, "api") + implicit val executionContext = system.executionContext + + val host = "0.0.0.0" + val port = 8080 + + val bindingFuture = Http() + .newServerAt(host, port) + .bind(Router.route) + + val keepAlive = Promise[Unit].future + Await.result(keepAlive, Duration.Inf) } From 84e94070ffb73d48237d96be7ea4775ec53710da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kapica?= Date: Sun, 23 Jun 2024 01:12:25 +0200 Subject: [PATCH 6/9] Add a sample log --- api/src/main/scala/Server.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/src/main/scala/Server.scala b/api/src/main/scala/Server.scala index bd54922..9de3913 100644 --- a/api/src/main/scala/Server.scala +++ b/api/src/main/scala/Server.scala @@ -19,6 +19,8 @@ object Server { .newServerAt(host, port) .bind(Router.route) + println(s"Server online at http://$host:$port/") + val keepAlive = Promise[Unit].future Await.result(keepAlive, Duration.Inf) From 84fcc421c8408d77bb98358118599ab52ada28ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kapica?= Date: Sun, 23 Jun 2024 01:35:05 +0200 Subject: [PATCH 7/9] Fix not concatenated routes --- api/src/main/scala/Router.scala | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/api/src/main/scala/Router.scala b/api/src/main/scala/Router.scala index 2ec974f..64a25b7 100644 --- a/api/src/main/scala/Router.scala +++ b/api/src/main/scala/Router.scala @@ -3,20 +3,27 @@ import akka.http.scaladsl.model.HttpEntity import akka.http.scaladsl.server.Directives.complete import akka.http.scaladsl.server.Directives.get import akka.http.scaladsl.server.Directives.path +import akka.http.scaladsl.server.Directives.pathSingleSlash import akka.http.scaladsl.server.Route +import akka.http.scaladsl.server.Directives._enhanceRouteWithConcatenation object Router { val route: Route = - path("hello") { + pathSingleSlash { get { - complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "

Say hello to akka-http

")) + complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "

Welcome to the API

")) } - } - path("health") { - get { - complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "

OK

")) + } ~ + path("hello") { + get { + complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "

Say hello to akka-http

")) + } + } ~ + path("health") { + get { + complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "

OK

")) + } } - } } From 474e328318c63d5b3eeab0b6efdc9fae4b2f2b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kapica?= Date: Sun, 23 Jun 2024 02:39:06 +0200 Subject: [PATCH 8/9] Update app.yaml --- .do/app.yaml | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/.do/app.yaml b/.do/app.yaml index 0c7110a..30f6a58 100644 --- a/.do/app.yaml +++ b/.do/app.yaml @@ -1,6 +1,12 @@ alerts: - rule: DEPLOYMENT_FAILED - rule: DOMAIN_FAILED +databases: + - cluster_name: elevator-system-db + engine: MONGODB + name: elevator-system-db + production: true + version: "7" features: - buildpack-stack=ubuntu-22 ingress: @@ -10,24 +16,23 @@ ingress: match: path: prefix: /api -jobs: - - dockerfile_path: api/Dockerfile - github: - branch: feature/4 - repo: mikolajkapica/elevator-system - instance_count: 1 - instance_size_slug: apps-s-1vcpu-0.5gb - source_dir: api -name: elevator-system +name: dolphin-app region: fra services: - - dockerfile_path: api/Dockerfile + - dockerfile_path: /api/Dockerfile + envs: + - key: DATABASE_URL + scope: RUN_TIME + value: ${elevator-system-db.DATABASE_URL} + - key: CA_CERT + scope: RUN_TIME + value: ${elevator-system-db.CA_CERT} github: branch: feature/4 + deploy_on_push: true repo: mikolajkapica/elevator-system http_port: 8080 - instance_count: 1 - instance_size_slug: apps-s-1vcpu-0.5gb + instance_count: 2 + instance_size_slug: apps-s-1vcpu-1gb name: elevator-system-api - run_command: sbt run - source_dir: api \ No newline at end of file + source_dir: api From 9f876f8d30afb1e4116aff0e5a5a9723f494ef50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Kapica?= Date: Sun, 23 Jun 2024 02:39:32 +0200 Subject: [PATCH 9/9] Update sample http server with db-test --- api/src/main/scala/Database.scala | 24 +++--------------------- api/src/main/scala/Helpers.scala | 2 +- api/src/main/scala/Router.scala | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/api/src/main/scala/Database.scala b/api/src/main/scala/Database.scala index 338d729..4783b16 100644 --- a/api/src/main/scala/Database.scala +++ b/api/src/main/scala/Database.scala @@ -1,27 +1,9 @@ -import org.mongodb.scala.Document import org.mongodb.scala.MongoClient -import org.mongodb.scala.MongoCollection - -import tour.Helpers._ +import org.mongodb.scala.MongoDatabase object Database { - def test(): Unit = - println("Connecting to MongoDB...") - val mongoClient = MongoClient(sys.env("DATABASE_URL")) - val database = mongoClient.getDatabase("mydb") - database.createCollection("test2") - val collection: MongoCollection[Document] = database.getCollection("test2") - - val document = Document( - "name" -> "MongoDB", - "type" -> "database", - "count" -> 1, - "info" -> Document("x" -> 203, "y" -> 102), - ) - - collection.insertOne(document).results() - collection.find().printResults() - println("Document inserted") + def connect(db_name: String): MongoDatabase = MongoClient(sys.env("DATABASE_URL")) + .getDatabase(db_name) } diff --git a/api/src/main/scala/Helpers.scala b/api/src/main/scala/Helpers.scala index eaafb52..3849f6c 100644 --- a/api/src/main/scala/Helpers.scala +++ b/api/src/main/scala/Helpers.scala @@ -42,7 +42,7 @@ object Helpers { def headResult() = Await.result(observable.head(), Duration(10, TimeUnit.SECONDS)) def printResults(initial: String = ""): Unit = { - if (initial.length > 0) + if (initial.nonEmpty) print(initial) results().foreach(res => println(converter(res))) } diff --git a/api/src/main/scala/Router.scala b/api/src/main/scala/Router.scala index 64a25b7..438d462 100644 --- a/api/src/main/scala/Router.scala +++ b/api/src/main/scala/Router.scala @@ -1,3 +1,4 @@ +import Database.connect import akka.http.scaladsl.model.ContentTypes import akka.http.scaladsl.model.HttpEntity import akka.http.scaladsl.server.Directives.complete @@ -6,6 +7,8 @@ import akka.http.scaladsl.server.Directives.path import akka.http.scaladsl.server.Directives.pathSingleSlash import akka.http.scaladsl.server.Route import akka.http.scaladsl.server.Directives._enhanceRouteWithConcatenation +import org.mongodb.scala.bson.collection.immutable.Document +import tour.Helpers._ object Router { @@ -24,6 +27,21 @@ object Router { get { complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "

OK

")) } + } ~ + path("db-test") { + get { + val db = connect("test") + db.createCollection("test") + db.getCollection("test").insertOne(Document("name" -> "test")).results() + val result = db.getCollection("test").find().results().map(_.toJson).mkString(", ") + + complete( + HttpEntity( + ContentTypes.`text/html(UTF-8)`, + s"

DB Test

Result: $result

", + ) + ) + } } }