Skip to content

Commit f749e1f

Browse files
committed
Add ServerWithCustomDispatcher
1 parent f31ac3b commit f749e1f

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package akkahttp
2+
3+
import org.apache.pekko.actor.ActorSystem
4+
import org.apache.pekko.http.scaladsl.Http
5+
import org.apache.pekko.http.scaladsl.model.{HttpResponse, StatusCodes}
6+
import org.apache.pekko.http.scaladsl.server.Directives.{complete, extractRequest, path, withExecutionContext}
7+
import org.apache.pekko.http.scaladsl.server.Route
8+
import org.slf4j.{Logger, LoggerFactory}
9+
10+
import scala.concurrent.{ExecutionContextExecutor, Future}
11+
import scala.util.{Failure, Success}
12+
13+
/**
14+
* By default, route directives run on the default dispatcher.
15+
* The `withExecutionContext` directive alone doesn't force execution on the custom dispatcher
16+
* it only makes the custom execution context available.
17+
* Wrapping a task in a Future explicitly runs the task on the custom execution context.
18+
*
19+
* Full example for this answer:
20+
* https://stackoverflow.com/questions/79141989/executioncontext-issue-in-akka-http-server/79145603#79145603
21+
*/
22+
object ServerWithCustomDispatcher extends App {
23+
val logger: Logger = LoggerFactory.getLogger(this.getClass)
24+
implicit val system: ActorSystem = ActorSystem()
25+
26+
implicit val myExCon: ExecutionContextExecutor = system.dispatchers.lookup(
27+
"custom-dispatcher-fork-join"
28+
)
29+
30+
val route: Route = {
31+
path("hello") {
32+
withExecutionContext(myExCon) {
33+
extractRequest { request =>
34+
// Move the operation inside a Future to ensure it runs on the custom dispatcher
35+
val result = Future {
36+
logger.info(s"Got request from client: ${request.getHeader("User-Agent")}")
37+
val msg = s"Execution context: $myExCon with thread: ${Thread.currentThread.getName}"
38+
logger.info(msg)
39+
HttpResponse(StatusCodes.OK, entity = s"$msg")
40+
}(myExCon)
41+
complete(result)
42+
}
43+
}
44+
}
45+
}
46+
47+
val bindingFuture = Http().newServerAt("localhost", 9000).bindFlow(route)
48+
49+
bindingFuture.onComplete {
50+
case Success(b) =>
51+
println("Server started, listening on: http://" + b.localAddress)
52+
case Failure(e) =>
53+
println(s"Server could not bind to... Exception message: ${e.getMessage}")
54+
system.terminate()
55+
}
56+
}

0 commit comments

Comments
 (0)