I started using Slick 3.0 in a new project a few months ago, and I had the same questions. Here is what I understood:
Slick 3.0 was designed for non-blocking asynchronous (reactive) applications. Obviously now it's Akka + Play / Spray. In this world, you mainly interact with Futures, so Slick db.run returns Future. It makes no sense to use Await.result - if you need to block calls, it is better to return to 2.x.
But if you use a jet stack, you will immediately get the benefits. For example, Spray is a fully non-blocking library that works well with Futures using onComplete . You can call a method that returns Future with the Slick result in the Spray route, and then use this result with onComplete. In this case, the entire response-response pipeline is not blocked.
You also mentioned exception handling, so this is exactly how you do it - using Futures.
So, based on my experience, I will write my method as follows:
def get(id: GPID): Future[Option[GPPerson]] = db.run( people.filter(_.id === id).result.map(_.headOption) )
and then work with the future.
source share