Scala Play 2.2 Slick 1.0.1-未来{尝试{...}}超时,等待免费可用连接 [英] Scala Play 2.2 Slick 1.0.1 - future { Try {...} } Timed out waiting for a free available connection

查看:66
本文介绍了Scala Play 2.2 Slick 1.0.1-未来{尝试{...}}超时,等待免费可用连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a scala.html page that makes AJAX calls in a Play 2.2.1, Scala 2.10.2, Slick 1.0.1, Postgres 9.3 application.

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

The following synchronous code works fine. It parses the request query string and calls the method Schools.findSchoolsByFilter, which makes a scala slick call to a table and filters the results based upon the SchoolFilter object and returns a 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秒后会引发此异常.我怀疑这可能是类似于本帖子玩光滑和异步-这是比赛条件吗?.我的问题是,如何更改此代码以安全地异步运行它?

If I change the method to run asynchronously (see below), and make multiple calls to listSchools, then after about 20 seconds this exception gets thrown. I suspect that it might be some sort of race condition akin to this post Play slick and Async - is it a race condition?. My question is, how should I change this code to safely run it asynchronously?

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.current.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

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连接问题的建议,我添加了"com.jolbox" % "bonecp" % "0.8.0.RELEASE"到我的库依赖项,以下内容到application.conf,并且仍然出现相同的行为.

Per the recommendations of Heroku/Play/BoneCp connection issues, I added "com.jolbox" % "bonecp" % "0.8.0.RELEASE" to my library dependencies and the following to application.conf and am still getting the same behavior.

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

推荐答案

您需要在将来之内打开会话.现在,您正在做相反的事情. withSession块结束后,Slick会话无效.如果您在该区块中打开一个Future,即使withSession区块结束并且该会话变为无效,它也会挂接到会话上.如果将来的代码尝试使用无效的会话,则会导致无法预料的行为.

You need to open the session WITHIN the future. Right now you are doing the opposite. A Slick session is not valid after the end of the withSession block. If you open a future within the block it hangs on to the session even after the withSession block ended and the session became invalid. If the future code tries to use the invalid session you end up with unpredictable behavior.

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

Or in other words move the db.withSession { implicit s: Session => call into the future {...} call.

这篇关于Scala Play 2.2 Slick 1.0.1-未来{尝试{...}}超时,等待免费可用连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆