Scala Play 2.2 Slick 1.0.1 - future {Try {...}}等待免费可用连接超时

 gjagtm2502855737 发布于 2023-02-08 15:53

我有一个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秒后抛出此异常.我怀疑它可能是某种竞争条件,类似于这篇文章播放光滑和异步 - 它是竞争条件吗?.我的问题是,我应该如何更改此代码以安全地异步运行它?

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(AbstractDispatch er.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连接问题的建议,我添加"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

cvogt.. 7

您需要在将来打开会话.现在你正在做相反的事情.在withSession块结束后,Slick会话无效.如果您在块中打开未来,即使在withSession块结束且会话无效之后,它仍会挂起到会话.如果将来的代码尝试使用无效会话,您最终会遇到不可预测的行为.

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

1 个回答
  • 您需要在将来打开会话.现在你正在做相反的事情.在withSession块结束后,Slick会话无效.如果您在块中打开未来,即使在withSession块结束且会话无效之后,它仍会挂起到会话.如果将来的代码尝试使用无效会话,您最终会遇到不可预测的行为.

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

    2023-02-08 15:54 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有