diff --git a/server/app/com/xsn/explorer/executors/DatabaseExecutionContext.scala b/server/app/com/xsn/explorer/executors/DatabaseExecutionContext.scala new file mode 100644 index 0000000..4c9e6f0 --- /dev/null +++ b/server/app/com/xsn/explorer/executors/DatabaseExecutionContext.scala @@ -0,0 +1,15 @@ +package com.xsn.explorer.executors + +import javax.inject.{Inject, Singleton} + +import akka.actor.ActorSystem +import play.api.libs.concurrent.CustomExecutionContext + +import scala.concurrent.ExecutionContext + +trait DatabaseExecutionContext extends ExecutionContext + +@Singleton +class DatabaseAkkaExecutionContext @Inject()(system: ActorSystem) + extends CustomExecutionContext(system, "database.dispatcher") + with DatabaseExecutionContext diff --git a/server/app/com/xsn/explorer/modules/ExecutorsModule.scala b/server/app/com/xsn/explorer/modules/ExecutorsModule.scala index f95c528..eac0805 100644 --- a/server/app/com/xsn/explorer/modules/ExecutorsModule.scala +++ b/server/app/com/xsn/explorer/modules/ExecutorsModule.scala @@ -1,11 +1,12 @@ package com.xsn.explorer.modules import com.google.inject.AbstractModule -import com.xsn.explorer.executors.{ExternalServiceAkkaExecutionContext, ExternalServiceExecutionContext} +import com.xsn.explorer.executors.{DatabaseAkkaExecutionContext, DatabaseExecutionContext, ExternalServiceAkkaExecutionContext, ExternalServiceExecutionContext} class ExecutorsModule extends AbstractModule { override def configure(): Unit = { bind(classOf[ExternalServiceExecutionContext]).to(classOf[ExternalServiceAkkaExecutionContext]) + bind(classOf[DatabaseExecutionContext]).to(classOf[DatabaseAkkaExecutionContext]) } } diff --git a/server/conf/application.conf b/server/conf/application.conf index 16383ec..393275c 100644 --- a/server/conf/application.conf +++ b/server/conf/application.conf @@ -60,6 +60,26 @@ play.evolutions { } } +# Number of database connections +# See https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing +fixedConnectionPool = 9 + +play.db { + prototype { + hikaricp.minimumIdle = ${fixedConnectionPool} + hikaricp.maximumPoolSize = ${fixedConnectionPool} + } +} + +# Job queue sized to HikariCP connection pool +database.dispatcher { + executor = "thread-pool-executor" + throughput = 1 + thread-pool-executor { + fixed-pool-size = ${fixedConnectionPool} + } +} + externalService.dispatcher { executor = "thread-pool-executor" throughput = 1 diff --git a/server/test/com/xsn/explorer/helpers/Executors.scala b/server/test/com/xsn/explorer/helpers/Executors.scala index cad3034..4cff7df 100644 --- a/server/test/com/xsn/explorer/helpers/Executors.scala +++ b/server/test/com/xsn/explorer/helpers/Executors.scala @@ -1,6 +1,6 @@ package com.xsn.explorer.helpers -import com.xsn.explorer.executors.ExternalServiceExecutionContext +import com.xsn.explorer.executors.{DatabaseExecutionContext, ExternalServiceExecutionContext} import scala.concurrent.ExecutionContext @@ -13,4 +13,10 @@ object Executors { override def reportFailure(cause: Throwable): Unit = globalEC.reportFailure(cause) } + + implicit val databaseEC: DatabaseExecutionContext = new DatabaseExecutionContext { + override def execute(runnable: Runnable): Unit = globalEC.execute(runnable) + + override def reportFailure(cause: Throwable): Unit = globalEC.reportFailure(cause) + } }