使用SecureSocial进行播放:在单独的线程池中运行DB IO

时间:2013-11-05 01:37:11

标签: scala playframework playframework-2.2 securesocial play-slick

我有一个Play 2.2.1应用,它使用play-slick 0.5.0.8将数据保存到Postgresql后端,SecureSocial 2.1.2来处理用户授权。

由于Play-slick事务是阻塞的,因此我在slick-context文件中创建了一个单独的/conf/application.conf执行上下文,根据instructions found in the plugin's Wiki

play {
  akka {
    actor {
      slick-context = {
        fork-join-executor {
          parallelism-min = 300
          parallelism-max = 300
        }
      }
    }
  }
}

这允许我创建一个在单独的执行上下文中运行的控制器Action,并且不会阻止默认线程池中的线程。例如。 /app/controllers/Application.scala

示例一 - 使用play-slick的DBAction:

import play.api.db.slick._
object Application extends Controller{ 

  // this controller Action won't block threads in the default pool since DBAction uses my separate slick-context execution context
  def recipes = DBAction { implicit rs =>
    val recipes  = Query(Recipes).list
    Ok(recipes.mkString)
  }

}

对于某些控制器操作,我希望能够将playSocial的操作(SecuredActionUserAwareAction等)与play-slick的DBAction结合使用。将两者结合起来的最佳方法是什么?

我意识到我可以执行类似下面的操作,但我的理解是DB调用不会使用我的单独slick-context,因此将阻止默认线程池:

示例二 - 使用SecureSocial的操作:

import play.api.db.slick._
import securesocial.core._
object Application extends Controller{ 

  // changing from a DBAction to a SecuredAction so that I can use SS's goodies
  def recipes = SecuredAction { implicit request =>
    val recipes  =  DB.withSession { implicit session:Session => Query(Recipes).list } // i'm guessing this WILL BLOCK the default thread pool since it isn't using my separate slick-context execution context??
    Ok(recipes.mkString)
  }

}

我是否正确假设示例二将使用/阻止默认线程池而不是单独的slick-context线程池?如果是这样,有没有办法改变这个?

我显然可以通过bumping up Play's default thread pooldefault-dispatcher)解决这个问题,但理想情况下我希望保持默认线程池非常精简,并在单独的池中运行所有阻塞数据库调用。

协助表示赞赏!

1 个答案:

答案 0 :(得分:7)

要回答你的问题,

  

假设示例二将使用/阻止默认值,我是否正确   线程池而不是我单独的光滑上下文线程池?如果是的话,

是的,那会耗尽/阻止默认池。

如果你想使用单独的slick-context线程池,你可以试试这样的东西吗?

  import scala.concurrent.Future

  // Note the use of '.async' |
  //                          V
  def recipes = SecuredAction.async { implicit request =>
    Future { // your code that may block
      val recipes  =  DB.withSession { implicit s:Session => 
        Query(Recipes).list 
      } 
      Ok(recipes.mkString)
    } 
  }

Future期望ExecutionContext(隐含的意志);所有你需要传递一个play-slick使用的(隐式):

import play.api._
implicit val slickExecutionContext = 
  Akka.system.dispatchers.lookup("play.akka.actor.slick-context")