I've been working on a small/medium web application, with approximately 10 endpoints. It's supposed to handle hundreds of simultaneous concurrent requests.
Because of my company policy I had to use javax.ws.rs for my controllers, so every controller method returns a javax.ws.rs.core.Response
Every controller depends on a Service, which is responsible to go to the database (DynamoDB, using the v2 non-blocking java dynamoDb sdk), obtain data from other microservices through http (Using org.asynhttpclient), and create the case class representing my response, so my controller can serialize it and return it as the body in the javax.ws.rs.core.Response.
Every component in my application is async and non-blocking, my services returns Future[Either[MyAppError, CaseClassRepresentingMyResponse]]. Then, in the controller, just at the end I Await for the future result, and create the javax.ws.rs.core.Response:
So my controllers looks like this:
class BarController(barService: BarService)(implicit ec: ExecutionContext) {
def getFoo(userId: BigInt, fooId: String): Response = withMetrics(Bar.ServiceName, Bar.GetFoo) {
val fooResponse = for {
_ <- EitherT(validateUserIdAndFooId(userId, fooId))
foo <- EitherT(barServiceService.getFoo(userId, fooId))
} yield foo
Await.result(fooResponse.value, 10 seconds) match {
case Success(Right(r)) => buildOkResponse(r)
case Success(Left(NotFound)) => HttpResponses.notFound
(.... a bunch of other cases ......)
}
}
}
(I am using cats EitherT to handle Future[Either[E, A]].)
Every component in my app receives an implicit ExecutionContext, and returns a Future[Either[E,A]].
Now, I've just finished all the coding and tests, and I need to provide a proper ExecutionContext in my configuration.
Would ExecutionContext.global be enough? Considering my code never blocks (since I am using DynamoDb non-blocking sdk and org.asynchttpclient), or should I create a different ExecutionContext? Maybe a from a FixedThreadPool? or a ForkJoinPool?