ps0604
ps0604

Reputation: 1081

Run transactionally and retrieve result in Future

How to run a transactionally statement in Slick 3.1.x, and capture the result in a Future (without the use of Await)?

This works (but uses Await)

 val action = db.run((for {
      _ <- table1.filter(_.id1 === id).delete
      _ <- table2.filter(_.id2=== id).delete
    } yield ()).transactionally)
    val result = Await.result(action, Duration.Inf)

However this does not print anything:

val future = db.run((for {
      _ <- table1.filter(_.id1 === id).delete
      _ <- table2.filter(_.id2=== id).delete
    } yield ()).transactionally)
 future.map { result => println("result:"+result) }

UPDATE

This is the real code taken from the program that doesn't work. It prints "1" but it never prints "2"

case class UserRole (sk: Int, name: String)

class UserRoleDB(tag: Tag) extends Table[UserRole](tag, "user_roles") {
  def sk = column[Int]("sk", O.PrimaryKey)
  def name = column[String]("name")
  def * = (sk, name) <>  ((UserRole.apply _).tupled, UserRole.unapply)
}

class Test extends Controller  {

  def index = Action.async { request =>

    val db = Database.forConfig("db1")
    val userRoles = TableQuery[UserRoleDB]
    val ur = UserRole(1002,"aaa")

    try {

          val action = (for {
                  userRole2 <- userRoles += ur
              } yield (userRole2)).transactionally

          val future = db.run(action)
          println(1)
//        val result = Await.result(future, Duration.Inf)
          future.map { result => {
             println(2)
             Ok("Finished OK")
           }
          }
      } 
      finally db.close

  }
}

Upvotes: 0

Views: 391

Answers (2)

Roman
Roman

Reputation: 5699

Coming from the other question you asked: You are opening and then immediately closing the db connection in the finally clause. Therefore your async db operation runs against a closed db connection. That's also why it works by using Await since that blocks the execution of db.close until you received the result set.

So how to fix this?

Either you move db.close into future.map or better you let play-slick handle db connections for you.

Side note

You should close your other question and update this thread accordingly instead.

Upvotes: 1

Paul Dolega
Paul Dolega

Reputation: 2476

Your second example is fine. My guess is that you are either running it in standalone program or in test - and it simply finishes before future has a chance to be executed.

Try to add some sleep after your code in your second sample and you'll see it is getting printed. This is definitely not something (this sleep) you would do in your actual code but it will show you it works as it should.

Upvotes: 1

Related Questions