我有一个 scala.html 页面,它在 Play 2.2.1、Scala 2.10.2、Slick 1.0.1、Postgres 9.3 应用程序中进行 AJAX 调用。
以下同步代码工作正常。它解析请求查询字符串并调用该方法Schools.findSchoolsByFilter
,它对表进行 scala 灵活调用,并根据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 秒后会抛出此异常。我怀疑这可能是某种类似于这篇文章的竞争条件发挥光滑和异步 - 这是一个竞争条件吗? https://stackoverflow.com/questions/18579684/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(会话.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.TaskInitation.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)
UPDATE
根据建议Heroku/Play/BoneCp 连接问题 https://stackoverflow.com/questions/15480506/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