Reputation: 4502
Suppose I have an application that executes an external command, which cannot be ran in parallel, as follows.
Future("command_to_run".run().exitValue())
The requirement for the application is that it should accepts requests and handle them sequentially by executing the command. The order that the requests are processed is not very important.
What would be the simplest or recommended way to achieve this requirement?
Upvotes: 0
Views: 43
Reputation: 20551
The simplest approach is probably, expanding on Feyyaz's answer, to define a single-thread ExecutionContext
:
val singlethread = ExecutionContext.fromExecutorService(Executors.newSingleThreadExecutor())
I recommend not making this context implicit, as you want only the execution of the command to happen in that context.
val execution = Future("command_to_run".run())(singleThread)
execution.map(_.exitValue) // will execute on the regular execution context in scope
The single thread context will then be in use for no longer than required to run the command and will then be available to serve the next request. In general, it's not a great idea to have
import scala.concurrent.ExecutionContext.Implicits.global
in production code, unless you really know what you're doing (IMO that the compiler suggests this is a horrible misfeature).
It's also worth considering using an Akka actor to synchronize running the command: this will simplify failure handling/cleanup and not require anything special in terms of ExecutionContext
s, at the expense of needing to work with the ActorSystem
Play supplies.
Upvotes: 1
Reputation: 3206
You can achieve it by defining a single-threaded execution context in the scope:
implicit val ec = ExecutionContext.fromExecutorService(Executors.newSingleThreadExecutor())
And if the global EC is imported, you'd need to remove it:
import scala.concurrent.ExecutionContext.Implicits.global // to be removed
Upvotes: 1