I am writing an Akka HTTP Web API, that connects to an Oracle Database instance using OJDBC.
To my knowledge there is no asynchronous JDBC API to connect to the database, nor there is a callback implementation, hence, a process thread must be blocked in order to complete the call.
My question is: having that Akka HTTP naturally allows handling request with Scala Future, is it a good idea to simply wrap the database call into a Scala Future? Does the underlying thread idle while waiting for the database response?
Handle the result of a future with methods like onComplete , or combinator methods like map , flatMap , filter , andThen , etc. The value in a Future is always an instance of one of the Try types: Success or Failure.
The Promise is a writable, single-assignment container that completes a Future. The Promise is similar to the Future. However, the Future is about the read-side of an asynchronous operation, while the Promise is about the write-side.
An ExecutionContext is similar to an Executor: it is free to execute computations in a new thread, in a pooled thread or in the current thread (although executing the computation in the current thread is discouraged – more on that below). The scala.
Does the underlying thread idle while waiting for the database response? Yes, the thread is blocked until JDBC call finishes. It's not a good thing, but until adba is ready there is probably no better option.
It is a common pattern to use Future for blocking IO like JDBC calls. There are some things to consider though. There's a great article on that topic on github.
Some points to sum up things described in the article:
wrap your blocking calls inside blocking
block, like that:
def fetchUser(id: Long): Future[User] = Future {
blocking { //mark this operation as blocking
...
preparedStatement.execute()
...
}
}
you shouldn't use scala.concurrent.ExecutionContext.Implicits.global
for futures that do any blocking, because you might starve thread pool. You should rather create a separate thread pool for your blocking operations:
object BlockingIOExecutionContext {
implicit val ec: ExecutionContextExecutor = ExecutionContext.fromExecutor(
Executors.newCachedThreadPool()
) // create seperate thread pool for our blocking operations
}
The best option for you would be just to use some kind of mature Scala frameworks, that do these things for you, like slick or doobie.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With