Why Akka http is not using custom execution context which I defined in this code and always falls back to default execution and default thread pool?
package com.vaz.www
import akka.actor.typed.ActorSystem
import akka.actor.typed.scaladsl.Behaviors
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route.seal
import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
import java.util.concurrent.Executors
import scala.io.StdIn
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import spray.json._
import akka.actor.typed.DispatcherSelector
import scala.concurrent.ExecutionContext
import scala.concurrent.ExecutionContextExecutor
import org.slf4j.LoggerFactory
object MyServer {
// implicit val ec: scala.concurrent.ExecutionContext =
// scala.concurrent.ExecutionContext.global // fromExecutorService(Executors.newFixedThreadPool(5))
def main(args: Array[String]): Unit = {
implicit val system = ActorSystem(Behaviors.empty, "Main")
implicit val myExCon: ExecutionContextExecutor = system.dispatchers.lookup(
DispatcherSelector.fromConfig("akka.actor.my-ex-con-dispatcher")
)
val logger = LoggerFactory.getLogger(getClass)
val route = {
withExecutionContext(myExCon) {
path("") {
get {
extractExecutionContext { implicit exec =>
println(
s"Execution and the thread:${Thread.currentThread().getName()}"
)
logger.info(
s"Execution and the thread:${Thread.currentThread().getName()}"
)
complete(
HttpEntity(
ContentTypes.`text/html(UTF-8)`,
"<h1>Hi</h1>"
)
)
}
}
}
}
}
val bindingFuture = Http().newServerAt("localhost", 9000).bind(route)
println(
s"Server now online. Please navigate to http://localhost:9000/hello\nPress RETURN to stop..."
)
StdIn.readLine()
bindingFuture.flatMap(_.unbind()).onComplete(_ => system.terminate())
}
}
my application conf
akka{
actor{
my-ex-con-dispatcher {
type = Dispatcher
executor = "fork-join-executor"
fork-join-executor {
parallelism-min = 2
parallelism-factor = 2.0
parallelism-max = 10
}
throughput = 100
}
}
}
the build.sbt
import Dependencies._
ThisBuild / scalaVersion := "3.3.4"
ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / organization := "com.example"
ThisBuild / organizationName := "example"
lazy val root = (project in file("."))
.settings(
name := "akka-server-example",
libraryDependencies += munit % Test
)
val AkkaVersion = "2.9.3"
val AkkaHttpVersion = "10.6.3"
resolvers += "Akka library repository".at("https://repo.akka.io/maven")
libraryDependencies += "com.typesafe.akka" %% "akka-http-spray-json" % AkkaHttpVersion
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor-typed" % AkkaVersion,
"com.typesafe.akka" %% "akka-stream" % AkkaVersion,
"com.typesafe.akka" %% "akka-http" % AkkaHttpVersion
)
when I curl localhost:9000, got the response as <h1>Hi</h1>
,
In the console I got this:
Server now online. Please navigate to http://localhost:9000/hello
Press RETURN to stop...
Execution and the thread:Main-akka.actor.default-dispatcher-8
I've tried reading akka [dispatcher] (https://doc.akka.io/libraries/akka/current/typed/dispatchers.html) but it is not working as expected,
I think the documentation and directive name is a bit misleading since it sounds a bit like the nested directives will run on the given execution context.
withExecutionContext
only puts the custom execution context in the request context for nested directives that are asynchronous and that use an execution context.
path
, get
and extractExecutionContext
are not asynchronous. extractExecutionContext
only provides a way to access the execution context from the request context to use your own logic.
There is no directive out of the box that will run all sub-directives on a given execution context. I don't think such a directive is generally useful, but it would be possible to compose your own directive always using a future, like @earthling-paul suggested, doing that.
Note that for non async directive trees, always having going through a future will come at a cost though.