1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2018 Make.org
4  *
5  * This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  *
18  */
19 
20 package org.make.api
21 
22 import akka.actor.typed.scaladsl.AskPattern.Askable
23 import akka.actor.typed.{ActorSystem, Scheduler}
24 import akka.cluster.typed.Cluster
25 import akka.http.scaladsl.Http
26 import akka.http.scaladsl.Http.ServerBinding
27 import akka.http.scaladsl.server.Route
28 import com.typesafe.config.{Config, ConfigFactory}
29 import grizzled.slf4j.Logging
30 import kamon.Kamon
31 import org.make.api.MakeGuardian.Initialize
32 import org.make.api.extensions.ThreadPoolMonitoringActor.MonitorThreadPool
33 import org.make.api.extensions.{DatabaseConfigurationExtension, MakeSettingsExtension, ThreadPoolMonitoringActor}
34 import org.make.api.technical.{ClusterShardingMonitor, MemoryMonitoringActor}
35 
36 import java.net.InetAddress
37 import java.nio.file.{Files, Paths}
38 import scala.concurrent.duration.DurationInt
39 import scala.concurrent.{Await, ExecutionContextExecutor, Future}
40 import scala.jdk.CollectionConverters._
41 
42 @SuppressWarnings(
43   Array("org.wartremover.warts.While", "org.wartremover.warts.ThreadSleep", "org.wartremover.warts.ScalaApp")
44 )
45 object MakeMain extends App with Logging with MakeApi {
46 
47   Thread.setDefaultUncaughtExceptionHandler { (thread, exception) =>
48     logger.error(s"Error in thread ${thread.getName}:", exception)
49   }
50 
51   val envName: Option[String] = Option(System.getenv("ENV_NAME"))
52 
53   private val resourceName = envName match {
54     case Some(name) if name.nonEmpty => s"$name-application.conf"
55     case _                           => "default-application.conf"
56   }
57 
58   private val configuration: Config = {
59     val defaultConfiguration = ConfigFactory.load(resourceName)
60     val configurationPath = defaultConfiguration.getString("make-api.secrets-configuration-path")
61     val extraConfigPath = Paths.get(configurationPath)
62     val configWithSecrets = if (Files.exists(extraConfigPath) && !Files.isDirectory(extraConfigPath)) {
63       ConfigFactory.parseFile(extraConfigPath.toFile).resolve().withFallback(defaultConfiguration)
64     } else {
65       defaultConfiguration
66     }
67 
68     val bindAddress = configWithSecrets.getString("akka.remote.artery.canonical.hostname")
69     val resolvedAddress: String = InetAddress.getByName(bindAddress).getHostAddress
70 
71     ConfigFactory
72       .parseMap(Map("akka.remote.artery.canonical.hostname" -> resolvedAddress).asJava)
73       .withFallback(configWithSecrets)
74       .resolve()
75   }
76 
77   override implicit val actorSystem: ActorSystem[MakeGuardian.GuardianCommand] =
78     ActorSystem(MakeGuardian.createBehavior(this), "make-api", configuration)
79 
80   implicit private val scheduler: Scheduler = actorSystem.scheduler
81 
82   // Wait until cluster is connected before initializing clustered actors
83   while (Cluster(actorSystem).state.leader.isEmpty) {
84     Thread.sleep(100)
85   }
86 
87   Kamon.init(configuration)
88 
89   private val databaseConfiguration = actorSystem.registerExtension(DatabaseConfigurationExtension)
90   databaseConfiguration.migrateDatabase()
91 
92   Await.result(elasticsearchClient.initialize(), 10.seconds)
93 
94   Await.result(swiftClient.init(), 10.seconds)
95 
96   Await.result(actorSystem ? Initialize, atMost = 5.seconds)
97 
98   actorSystem.systemActorOf(ClusterShardingMonitor(), ClusterShardingMonitor.name)
99   actorSystem.systemActorOf(MemoryMonitoringActor(), MemoryMonitoringActor.name)
100   private val threadPoolMonitor =
101     actorSystem.systemActorOf(ThreadPoolMonitoringActor(), ThreadPoolMonitoringActor.name)
102   threadPoolMonitor ! MonitorThreadPool(databaseConfiguration.readExecutor, "db-read-pool")
103   threadPoolMonitor ! MonitorThreadPool(databaseConfiguration.writeExecutor, "db-write-pool")
104 
105   private val settings = MakeSettingsExtension(actorSystem)
106 
107   // Ensure database stuff is initialized
108   Await.result(userService.getUserByEmail(settings.defaultAdmin.email), atMost = 20.seconds)
109 
110   implicit val ec: ExecutionContextExecutor = actorSystem.executionContext
111 
112   private val host = settings.Http.host
113   private val port = settings.Http.port
114 
115   val bindingFuture: Future[ServerBinding] =
116     Http().newServerAt(interface = host, port = port).bind(Route.toFunction(makeRoutes))
117 
118   bindingFuture.map { serverBinding =>
119     logger.info(s"Make API bound to ${serverBinding.localAddress} ")
120   }.onComplete {
121     case util.Failure(ex) =>
122       logger.error(s"Failed to bind to $host:$port!", ex)
123       actorSystem.terminate()
124     case _ =>
125   }
126 
127 }
Line Stmt Id Pos Tree Symbol Tests Code
47 34959 1835 - 1972 Apply java.lang.Thread.setDefaultUncaughtExceptionHandler java.lang.Thread.setDefaultUncaughtExceptionHandler(((thread: Thread, exception: Throwable) => MakeMain.this.logger.error(("Error in thread ".+(thread.getName()).+(":"): String), exception)))
48 42821 1906 - 1968 Apply grizzled.slf4j.Logger.error MakeMain.this.logger.error(("Error in thread ".+(thread.getName()).+(":"): String), exception)
51 47726 2013 - 2038 Apply java.lang.System.getenv java.lang.System.getenv("ENV_NAME")
51 40136 2006 - 2039 Apply scala.Option.apply scala.Option.apply[String](java.lang.System.getenv("ENV_NAME"))
53 33028 2070 - 2077 Select org.make.api.MakeMain.envName MakeMain.this.envName
54 49348 2109 - 2122 Select scala.collection.StringOps.nonEmpty scala.Predef.augmentString(name).nonEmpty
55 41240 2192 - 2218 Literal <nosymbol> "default-application.conf"
59 47427 2295 - 2327 Apply com.typesafe.config.ConfigFactory.load com.typesafe.config.ConfigFactory.load(MakeMain.this.resourceName)
59 33363 2314 - 2326 Select org.make.api.MakeMain.resourceName MakeMain.this.resourceName
60 43286 2356 - 2425 Apply com.typesafe.config.Config.getString defaultConfiguration.getString("make-api.secrets-configuration-path")
61 34997 2452 - 2480 Apply java.nio.file.Paths.get java.nio.file.Paths.get(configurationPath)
62 47765 2546 - 2581 Select scala.Boolean.unary_! java.nio.file.Files.isDirectory(extraConfigPath).unary_!
62 39899 2513 - 2581 Apply scala.Boolean.&& java.nio.file.Files.exists(extraConfigPath).&&(java.nio.file.Files.isDirectory(extraConfigPath).unary_!)
63 48794 2591 - 2683 Block com.typesafe.config.Config.withFallback com.typesafe.config.ConfigFactory.parseFile(extraConfigPath.toFile()).resolve().withFallback(defaultConfiguration)
63 33072 2591 - 2683 Apply com.typesafe.config.Config.withFallback com.typesafe.config.ConfigFactory.parseFile(extraConfigPath.toFile()).resolve().withFallback(defaultConfiguration)
65 40994 2703 - 2723 Ident org.make.api.MakeMain.defaultConfiguration defaultConfiguration
68 33407 2753 - 2821 Apply com.typesafe.config.Config.getString configWithSecrets.getString("akka.remote.artery.canonical.hostname")
69 47172 2856 - 2905 Apply java.net.InetAddress.getHostAddress java.net.InetAddress.getByName(bindAddress).getHostAddress()
74 39609 2911 - 3068 Apply com.typesafe.config.Config.resolve com.typesafe.config.ConfigFactory.parseMap(scala.jdk.CollectionConverters.MapHasAsJava[String, String](scala.Predef.Map.apply[String, String](scala.Predef.ArrowAssoc[String]("akka.remote.artery.canonical.hostname").->[String](resolvedAddress))).asJava).withFallback(configWithSecrets).resolve()
78 40699 3218 - 3231 Select org.make.api.MakeMain.configuration MakeMain.this.configuration
78 47517 3206 - 3216 Literal <nosymbol> "make-api"
78 35191 3171 - 3204 Apply org.make.api.MakeGuardian.createBehavior MakeGuardian.createBehavior(this)
78 32813 3159 - 3232 Apply akka.actor.typed.ActorSystem.apply akka.actor.typed.ActorSystem.apply[org.make.api.MakeGuardian.GuardianCommand](MakeGuardian.createBehavior(this), "make-api", MakeMain.this.configuration)
80 49850 3280 - 3301 Select akka.actor.typed.ActorSystem.scheduler MakeMain.this.actorSystem.scheduler
83 48265 3379 - 3379 Literal <nosymbol> ()
83 41730 3394 - 3405 Select org.make.api.MakeMain.actorSystem MakeMain.this.actorSystem
83 33147 3386 - 3427 Select scala.Option.isEmpty akka.cluster.typed.Cluster.apply(MakeMain.this.actorSystem).state.leader.isEmpty
83 34952 3435 - 3452 Block <nosymbol> { java.lang.Thread.sleep(100L); while$1() }
83 40445 3379 - 3379 Block <nosymbol> ()
84 47209 3435 - 3452 Apply java.lang.Thread.sleep java.lang.Thread.sleep(100L)
84 38338 3447 - 3447 Apply org.make.api.MakeMain.while$1 while$1()
87 32855 3471 - 3484 Select org.make.api.MakeMain.configuration MakeMain.this.configuration
87 49336 3460 - 3485 Apply kamon.Init.init kamon.Kamon.init(MakeMain.this.configuration)
89 33356 3525 - 3586 Apply akka.actor.typed.Extensions.registerExtension MakeMain.this.actorSystem.registerExtension[org.make.api.extensions.DatabaseConfigurationExtension](org.make.api.extensions.DatabaseConfigurationExtension)
89 41487 3555 - 3585 Select org.make.api.extensions.DatabaseConfigurationExtension org.make.api.extensions.DatabaseConfigurationExtension
90 46957 3589 - 3628 Apply org.make.api.extensions.DatabaseConfiguration.migrateDatabase MakeMain.this.databaseConfiguration.migrateDatabase()
92 48022 3679 - 3689 Select scala.concurrent.duration.DurationConversions.seconds scala.concurrent.duration.`package`.DurationInt(10).seconds
92 39396 3645 - 3677 Apply org.make.api.technical.elasticsearch.ElasticsearchClient.initialize MakeMain.this.elasticsearchClient.initialize()
92 39895 3632 - 3690 Apply scala.concurrent.Await.result scala.concurrent.Await.result[Unit](MakeMain.this.elasticsearchClient.initialize(), scala.concurrent.duration.`package`.DurationInt(10).seconds)
92 34987 3679 - 3681 Literal <nosymbol> 10
94 45376 3727 - 3729 Literal <nosymbol> 10
94 32898 3707 - 3725 Apply org.make.swift.SwiftClient.init MakeMain.this.swiftClient.init()
94 34423 3694 - 3738 Apply scala.concurrent.Await.result scala.concurrent.Await.result[Unit](MakeMain.this.swiftClient.init(), scala.concurrent.duration.`package`.DurationInt(10).seconds)
94 41525 3727 - 3737 Select scala.concurrent.duration.DurationConversions.seconds scala.concurrent.duration.`package`.DurationInt(10).seconds
96 32044 3790 - 3791 Literal <nosymbol> 5
96 39930 3755 - 3779 ApplyToImplicitArgs akka.actor.typed.scaladsl.AskPattern.Askable.? akka.actor.typed.scaladsl.AskPattern.Askable[org.make.api.MakeGuardian.GuardianCommand](MakeMain.this.actorSystem).?[org.make.api.MakeGuardian.Initialized.type](org.make.api.MakeGuardian.Initialize)(MakeMain.this.timeout, MakeMain.this.scheduler)
96 47507 3767 - 3767 Select org.make.api.MakeMain.scheduler MakeMain.this.scheduler
96 34752 3767 - 3767 Select org.make.api.MakeApi.timeout MakeMain.this.timeout
96 46415 3755 - 3766 Select org.make.api.MakeMain.actorSystem MakeMain.this.actorSystem
96 45422 3790 - 3799 Select scala.concurrent.duration.DurationConversions.seconds scala.concurrent.duration.`package`.DurationInt(5).seconds
96 38893 3769 - 3779 Select org.make.api.MakeGuardian.Initialize org.make.api.MakeGuardian.Initialize
96 41279 3742 - 3800 Apply scala.concurrent.Await.result scala.concurrent.Await.result[org.make.api.MakeGuardian.Initialized.type](akka.actor.typed.scaladsl.AskPattern.Askable[org.make.api.MakeGuardian.GuardianCommand](MakeMain.this.actorSystem).?[org.make.api.MakeGuardian.Initialized.type](org.make.api.MakeGuardian.Initialize)(MakeMain.this.timeout, MakeMain.this.scheduler), scala.concurrent.duration.`package`.DurationInt(5).seconds)
98 39352 3816 - 3816 TypeApply akka.actor.typed.ActorSystem.systemActorOf$default$3 MakeMain.this.actorSystem.systemActorOf$default$3[Nothing]
98 33142 3830 - 3854 Apply org.make.api.technical.ClusterShardingMonitor.apply org.make.api.technical.ClusterShardingMonitor.apply()
98 34784 3804 - 3884 Apply akka.actor.typed.ActorSystem.systemActorOf MakeMain.this.actorSystem.systemActorOf[org.make.api.technical.ClusterShardingMonitor.Protocol](org.make.api.technical.ClusterShardingMonitor.apply(), org.make.api.technical.ClusterShardingMonitor.name, MakeMain.this.actorSystem.systemActorOf$default$3[Nothing])
98 46450 3856 - 3883 Select org.make.api.technical.ClusterShardingMonitor.name org.make.api.technical.ClusterShardingMonitor.name
99 45884 3887 - 3965 Apply akka.actor.typed.ActorSystem.systemActorOf MakeMain.this.actorSystem.systemActorOf[org.make.api.technical.MemoryMonitoringActor.Monitor.type](org.make.api.technical.MemoryMonitoringActor.apply(), org.make.api.technical.MemoryMonitoringActor.name, MakeMain.this.actorSystem.systemActorOf$default$3[Nothing])
99 48569 3913 - 3936 Apply org.make.api.technical.MemoryMonitoringActor.apply org.make.api.technical.MemoryMonitoringActor.apply()
99 32850 3899 - 3899 TypeApply akka.actor.typed.ActorSystem.systemActorOf$default$3 MakeMain.this.actorSystem.systemActorOf$default$3[Nothing]
99 39686 3938 - 3964 Select org.make.api.technical.MemoryMonitoringActor.name org.make.api.technical.MemoryMonitoringActor.name
101 33183 4059 - 4089 Select org.make.api.extensions.ThreadPoolMonitoringActor.name org.make.api.extensions.ThreadPoolMonitoringActor.name
101 46205 4016 - 4016 TypeApply akka.actor.typed.ActorSystem.systemActorOf$default$3 MakeMain.this.actorSystem.systemActorOf$default$3[Nothing]
101 39392 4004 - 4090 Apply akka.actor.typed.ActorSystem.systemActorOf MakeMain.this.actorSystem.systemActorOf[org.make.api.extensions.ThreadPoolMonitoringActor.Protocol](org.make.api.extensions.ThreadPoolMonitoringActor.apply(), org.make.api.extensions.ThreadPoolMonitoringActor.name, MakeMain.this.actorSystem.systemActorOf$default$3[Nothing])
101 41321 4030 - 4057 Apply org.make.api.extensions.ThreadPoolMonitoringActor.apply org.make.api.extensions.ThreadPoolMonitoringActor.apply()
102 45923 4093 - 4182 Apply akka.actor.typed.ActorRef.ActorRefOps.! typed.this.ActorRef.ActorRefOps[org.make.api.extensions.ThreadPoolMonitoringActor.Protocol](MakeMain.this.threadPoolMonitor).!(org.make.api.extensions.ThreadPoolMonitoringActor.MonitorThreadPool.apply(MakeMain.this.databaseConfiguration.readExecutor, "db-read-pool"))
102 39723 4167 - 4181 Literal <nosymbol> "db-read-pool"
102 31516 4093 - 4110 Select org.make.api.MakeMain.threadPoolMonitor MakeMain.this.threadPoolMonitor
102 32592 4113 - 4182 Apply org.make.api.extensions.ThreadPoolMonitoringActor.MonitorThreadPool.apply org.make.api.extensions.ThreadPoolMonitoringActor.MonitorThreadPool.apply(MakeMain.this.databaseConfiguration.readExecutor, "db-read-pool")
102 48609 4131 - 4165 Select org.make.api.extensions.DatabaseConfiguration.readExecutor MakeMain.this.databaseConfiguration.readExecutor
103 34257 4223 - 4258 Select org.make.api.extensions.DatabaseConfiguration.writeExecutor MakeMain.this.databaseConfiguration.writeExecutor
103 31559 4185 - 4276 Apply akka.actor.typed.ActorRef.ActorRefOps.! typed.this.ActorRef.ActorRefOps[org.make.api.extensions.ThreadPoolMonitoringActor.Protocol](MakeMain.this.threadPoolMonitor).!(org.make.api.extensions.ThreadPoolMonitoringActor.MonitorThreadPool.apply(MakeMain.this.databaseConfiguration.writeExecutor, "db-write-pool"))
103 39143 4205 - 4276 Apply org.make.api.extensions.ThreadPoolMonitoringActor.MonitorThreadPool.apply org.make.api.extensions.ThreadPoolMonitoringActor.MonitorThreadPool.apply(MakeMain.this.databaseConfiguration.writeExecutor, "db-write-pool")
103 41511 4185 - 4202 Select org.make.api.MakeMain.threadPoolMonitor MakeMain.this.threadPoolMonitor
103 46996 4260 - 4275 Literal <nosymbol> "db-write-pool"
105 48045 4325 - 4336 Select org.make.api.MakeMain.actorSystem MakeMain.this.actorSystem
105 40786 4303 - 4337 Apply akka.actor.typed.ExtensionId.apply org.make.api.extensions.MakeSettingsExtension.apply(MakeMain.this.actorSystem)
108 33688 4462 - 4472 Select scala.concurrent.duration.DurationConversions.seconds scala.concurrent.duration.`package`.DurationInt(20).seconds
108 45677 4396 - 4451 Apply org.make.api.user.UserService.getUserByEmail MakeMain.this.userService.getUserByEmail(MakeMain.this.settings.defaultAdmin.email)
108 32632 4423 - 4450 Select org.make.api.extensions.MakeSettings.DefaultAdmin.email MakeMain.this.settings.defaultAdmin.email
108 37554 4462 - 4464 Literal <nosymbol> 20
108 46749 4383 - 4473 Apply scala.concurrent.Await.result scala.concurrent.Await.result[Option[org.make.core.user.User]](MakeMain.this.userService.getUserByEmail(MakeMain.this.settings.defaultAdmin.email), scala.concurrent.duration.`package`.DurationInt(20).seconds)
110 39184 4521 - 4549 Select akka.actor.typed.ActorSystem.executionContext MakeMain.this.actorSystem.executionContext
112 31033 4572 - 4590 Select org.make.api.extensions.MakeSettings.Http.host MakeMain.this.settings.Http.host
113 47804 4612 - 4630 Select org.make.api.extensions.MakeSettings.Http.port MakeMain.this.settings.Http.port
116 45714 4725 - 4729 Select org.make.api.MakeMain.port MakeMain.this.port
116 33443 4736 - 4764 ApplyToImplicitArgs akka.http.scaladsl.server.Route.toFunction akka.http.scaladsl.server.Route.toFunction(MakeMain.this.makeRoutes)(MakeMain.this.actorSystem)
116 37592 4752 - 4752 Select org.make.api.MakeMain.actorSystem MakeMain.this.actorSystem
116 46196 4681 - 4765 Apply akka.http.scaladsl.ServerBuilder.bind akka.http.scaladsl.Http.apply()(MakeMain.this.actorSystem).newServerAt(MakeMain.this.host, MakeMain.this.port).bind(akka.http.scaladsl.server.Route.toFunction(MakeMain.this.makeRoutes)(MakeMain.this.actorSystem))
116 39674 4685 - 4685 Select org.make.api.MakeMain.actorSystem MakeMain.this.actorSystem
116 32385 4712 - 4716 Select org.make.api.MakeMain.host MakeMain.this.host
118 30777 4787 - 4787 Select org.make.api.MakeMain.ec MakeMain.this.ec
119 38941 4810 - 4874 Apply grizzled.slf4j.Logger.info MakeMain.this.logger.info(("Make API bound to ".+(serverBinding.localAddress).+(" "): String))
120 45198 4890 - 4890 Select org.make.api.MakeMain.ec MakeMain.this.ec
120 37344 4769 - 5026 ApplyToImplicitArgs scala.concurrent.Future.onComplete MakeMain.this.bindingFuture.map[Unit](((serverBinding: akka.http.scaladsl.Http.ServerBinding) => MakeMain.this.logger.info(("Make API bound to ".+(serverBinding.localAddress).+(" "): String))))(MakeMain.this.ec).onComplete[Unit](((x0$1: scala.util.Try[Unit]) => x0$1 match { case (exception: Throwable): scala.util.Failure[Unit]((ex @ _)) => { MakeMain.this.logger.error(("Failed to bind to ".+(MakeMain.this.host).+(":").+(MakeMain.this.port).+("!"): String), ex); MakeMain.this.actorSystem.terminate() } case _ => () }))(MakeMain.this.ec)
122 47840 4927 - 4978 Apply grizzled.slf4j.Logger.error MakeMain.this.logger.error(("Failed to bind to ".+(MakeMain.this.host).+(":").+(MakeMain.this.port).+("!"): String), ex)
123 40738 4985 - 5008 Apply akka.actor.typed.ActorSystem.terminate MakeMain.this.actorSystem.terminate()
124 31828 5020 - 5022 Literal <nosymbol> ()