Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JDBC calls wrapped in Scala Future

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?

like image 670
Massimiliano Avatar asked May 11 '19 17:05

Massimiliano


People also ask

How do you handle future Scala?

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.

What is future and promise in Scala?

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.

What is Scala execution context?

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.


1 Answers

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.

like image 196
Krzysztof Atłasik Avatar answered Sep 18 '22 08:09

Krzysztof Atłasik