【问题标题】:Scala Play 2.2 Slick 1.0.1 - future { Try {...} } Timed out waiting for a free available connectionScala Play 2.2 Slick 1.0.1 - 未来 { Try {...} } 等待免费可用连接超时
【发布时间】:2013-12-22 23:59:55
【问题描述】:

我有一个 scala.html 页面,它在 Play 2.2.1、Scala 2.10.2、Slick 1.0.1、Postgres 9.3 应用程序中进行 AJAX 调用。

以下同步代码可以正常工作。它解析请求查询字符串并调用方法Schools.findSchoolsByFilter,该方法对表进行scala slick调用并根据SchoolFilter对象过滤结果并返回Try[List[School]]

def listSchools = Action { implicit request =>
  db.withSession { implicit s: Session =>
    Schools.findSchoolsByFilter(parseFilter) match {
      case Success(schools) => Ok(toJsArray(schools))
      case Failure(e) => Ok(e.getMessage)
    }
  }
}

如果我将方法更改为异步运行(见下文),并多次调用 listSchools,则大约 20 秒后会引发此异常。我怀疑这可能是类似于这篇文章Play slick and Async - is it a race condition? 的某种竞争条件。我的问题是,我应该如何更改此代码以安全地异步运行它?

def listSchools = Action.async { implicit request =>
  db.withSession { implicit s: Session =>
    Schools.findSchoolsByFilter(parseFilter) map {
      case Success(schools) => Ok(toJsArray(schools))
      case Failure(e) => Ok(e.getMessage)
    }
  }
}
def findSchoolsByFilter(f: SchoolFilter, n: Int)(implicit s: Session) = 
  future { Try {
    ...
}}
case class SchoolFilter(name: Option[String], 
                        city: Option[String], 
                        state: Option[String],
                        zip: Option[String], 
                        district: Option[String])

这是我的依赖项:

libraryDependencies ++= Seq(
  jdbc,
  cache,
  "com.typesafe.slick" %% "slick" % "1.0.1",
  "com.github.tototoshi" %% "slick-joda-mapper" % "0.4.0",
  "org.scalatest" % "scalatest_2.10" % "2.0" % "test",
  "org.easymock" % "easymock" % "3.2",
  "org.postgresql" % "postgresql" % "9.3-1100-jdbc4"
)

这是堆栈跟踪:

com.jolbox.bonecp.DefaultConnectionStrategy.getConnectionInternal(DefaultConnectionStrategy.java:88) com.jolbox.bonecp.AbstractConnectionStrategy.getConnection(AbstractConnectionStrategy.java:90) com.jolbox.bonecp.BoneCP.getConnection(BoneCP.java:553) com.jolbox.bonecp.BoneCPDataSource.getConnection(BoneCPDataSource.java:131) scala.slick.session.Database$$anon$1.createConnection(Database.scala:82) scala.slick.session.BaseSession.conn$lzycompute(Session.scala:207) scala.slick.session.BaseSession.conn(Session.scala:207) scala.slick.session.Session$class.prepareStatement(Session.scala:29) scala.slick.session.BaseSession.prepareStatement(Session.scala:201) scala.slick.jdbc.StatementInvoker.results(StatementInvoker.scala:29) scala.slick.jdbc.StatementInvoker.elementsTo(StatementInvoker.scala:17) scala.slick.jdbc.Invoker$class.foreach(Invoker.scala:90) scala.slick.jdbc.StatementInvoker.foreach(StatementInvoker.scala:10) scala.slick.jdbc.Invoker$class.build(Invoker.scala:66) scala.slick.jdbc.StatementInvoker.build(StatementInvoker.scala:10) scala.slick.jdbc.Invoker$class.list(Invoker.scala:56) scala.slick.jdbc.StatementInvoker.list(StatementInvoker.scala:10) scala.slick.jdbc.UnitInvoker$class.list(Invoker.scala:150) scala.slick.driver.BasicInvokerComponent$QueryInvoker.list(BasicInvokerComponent.scala:19) models.school.Schools$$anonfun$findSchoolsByFilter$1$$anonfun$apply$5.apply(School.scala:85) models.school.Schools$$anonfun$findSchoolsByFilter$1$$anonfun$apply$5.apply(School.scala:84) scala.util.Try$.apply(Try.scala:161) models.school.Schools$$anonfun$findSchoolsByFilter$1.apply(School.scala:84) models.school.Schools$$anonfun$findSchoolsByFilter$1.apply(School.scala:84) scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:42) akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:386) scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

更新

根据Heroku/Play/BoneCp connection issues 的建议,我将"com.jolbox" % "bonecp" % "0.8.0.RELEASE" 添加到我的库依赖项中,并将以下内容添加到application.conf 中,并且仍然得到相同的行为。

db.default.idleMaxAge=10 minutes
db.default.idleConnectionTestPeriod=30 seconds
db.default.connectionTimeout=20 second
db.default.connectionTestStatement="SELECT 1"
db.default.maxConnectionAge=30 minutes

【问题讨论】:

    标签: scala playframework-2.0 slick


    【解决方案1】:

    您需要在未来打开会话。现在你正在做相反的事情。在withSession 块结束后,Slick 会话无效。如果您在块中打开未来,即使在 withSession 块结束并且会话变得无效之后,它也会挂起会话。如果未来的代码尝试使用无效会话,您最终会出现不可预知的行为。

    或者换句话说,将db.withSession { implicit s: Session => 调用移到future {...} 调用中。

    【讨论】:

      猜你喜欢
      • 2015-11-03
      • 1970-01-01
      • 1970-01-01
      • 2016-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-16
      • 2011-03-06
      相关资源
      最近更新 更多