The “Right” Way to Use Slick 3.0 Scala Requests to Write to the Play Framework

I use Slick 3.0 and (of course) almost all the examples out there cover Slick 2.x. Everything has changed and, frankly, it seemed more complicated, no less.

Here is an example: I want to get an object (GPPerson) by id. This is what I have now and it seems very verbose ... more than Slick 2.x:

def get(id: GPID): Option[GPPerson] = Await.result( db.run( people.filter(_.id === id).result), Duration.Inf ).headOption 

In Slick 2.x, things were easier due to implications, among other things. But the above seems to be the most concise expression that I came up with.

It also does not apply to exception handling, which I will need to add.

+6
source share
2 answers

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.

+4
source

can you do this.

 def syncResult[R](action:slick.dbio.DBIOAction[R, slick.dbio.NoStream, scala.Nothing]):R = { import scala.concurrent.duration.Duration val db = Database.forConfig("db") try { Await.result(db.run(action), Duration.Inf) } finally db.close } def get(id: GPID): Option[GPPerson] = syncResult { people.filter(_.id === id).result.headOption } 
+1
source

Source: https://habr.com/ru/post/987539/


All Articles