d-_-b
d-_-b

Reputation: 4502

How should a Play application be set up to handle requests sequentially at a time?

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

Answers (2)

Levi Ramsey
Levi Ramsey

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 ExecutionContexts, at the expense of needing to work with the ActorSystem Play supplies.

Upvotes: 1

Feyyaz
Feyyaz

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

Related Questions