在规范“从java.util.concurrent.ThreadPoolExecutor拒绝的任务slick.backend.DatabaseComponent"中播放Slick异常. [英] Play Slick exception in Specs "Task slick.backend.DatabaseComponent rejected from java.util.concurrent.ThreadPoolExecutor"

查看:192
本文介绍了在规范“从java.util.concurrent.ThreadPoolExecutor拒绝的任务slick.backend.DatabaseComponent"中播放Slick异常.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在运行Spec测试时使用Play从Slick获取ThreadPoolException,这是使用Play 2.4.x,Slick 3,Specs 2吗?

I am getting a ThreadPoolException from Slick using Play when running my Spec tests, This is using Play 2.4.x, Slick 3, Specs 2?

我的测试如下:

val jsonHeaders = FakeHeaders(Seq((CONTENT_TYPE, MimeTypes.JSON)))
def fakeApp: FakeApplication = FakeApplication(additionalConfiguration = Map(
  "slick.dbs.default.driver" -> "slick.driver.H2Driver$",
  "slick.dbs.default.db.driver" -> "org.h2.Driver",
  "slick.dbs.default.db.url" -> "jdbc:h2:mem:test;MODE=PostgreSQL;DATABASE_TO_UPPER=FALSE"
))

"Add new group" in new WithApplication(FakeApp.fakeApp){
  val vg = new ViewGroup(0, "Test", "Tests")
  val add = route(FakeRequest(POST, "/api/new-group", jsonHeaders, vg.toJson())).get

  status(add) must equalTo(OK)
  contentType(add) must beSome.which(_ == MimeTypes.JSON)
}

哪个叫端点:

def newGroup = AuthenticatedAction(authType).async(parse.json) { request =>
  request.body.validate[ViewGroup].fold(
    errors => {
      Future { BadRequest(JsError.toJson(errors)) }
    }, viewGroup => {
      Groups.add(new Group(viewGroup.Name, viewGroup.Description)).map( i => Ok(i.toString) )
    }
  )
}

依次调用DAO:

object Groups {
  val groups = TableQuery[GroupTableDef]
  val dbConfig = DatabaseConfigProvider.get[JdbcProfile](Play.current)

  def add(group: Group): Future[Int] = {
    dbConfig.db.run(groups += group)
  }
}

运行测试时,出现以下错误:

When I run the tests, I get the following errors:

[error]   ! Add new group
[error]    Task slick.backend.DatabaseComponent$DatabaseDef$$anon$2@10277fb0 rejected from java.util.concurrent.ThreadPoolExecutor@794e3935[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 9] (DatabaseComponent.scala:230)
[error] slick.backend.DatabaseComponent$DatabaseDef$class.runSynchronousDatabaseAction(DatabaseComponent.scala:230)
[error] slick.jdbc.JdbcBackend$DatabaseDef.runSynchronousDatabaseAction(JdbcBackend.scala:38)
[error] slick.backend.DatabaseComponent$DatabaseDef$class.runInContext(DatabaseComponent.scala:207)
[error] slick.jdbc.JdbcBackend$DatabaseDef.runInContext(JdbcBackend.scala:38)
[error] slick.backend.DatabaseComponent$DatabaseDef$class.runInternal(DatabaseComponent.scala:75)
[error] slick.jdbc.JdbcBackend$DatabaseDef.runInternal(JdbcBackend.scala:38)
[error] slick.backend.DatabaseComponent$DatabaseDef$class.run(DatabaseComponent.scala:72)
[error] slick.jdbc.JdbcBackend$DatabaseDef.run(JdbcBackend.scala:38)
[error] database.Groups$.add(Group.scala:33)
[error] controllers.AuthenticationAPIv1$$anonfun$newGroup$1$$anonfun$apply$13.apply(AuthenticationAPIv1.scala:74)
[error] controllers.AuthenticationAPIv1$$anonfun$newGroup$1$$anonfun$apply$13.apply(AuthenticationAPIv1.scala:73)
[error] play.api.libs.json.JsResult$class.fold(JsResult.scala:72)
[error] play.api.libs.json.JsSuccess.fold(JsResult.scala:9)
[error] controllers.AuthenticationAPIv1$$anonfun$newGroup$1.apply(AuthenticationAPIv1.scala:70)
[error] controllers.AuthenticationAPIv1$$anonfun$newGroup$1.apply(AuthenticationAPIv1.scala:69)
[error] auth.scala.AuthenticatedActionBuilder$$anon$1.invokeBlock(AuthenticatedActionBuilder.scala:23)
[error] auth.scala.AuthenticatedActionBuilder$$anon$1.invokeBlock(AuthenticatedActionBuilder.scala:19)
[error] play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:493)
[error] play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105)
[error] play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105)
[error] play.utils.Threads$.withContextClassLoader(Threads.scala:21)
[error] play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:104)
[error] play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:103)
[error] play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:103)
[error] play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:96)
[error] play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:524)
[error] play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:524)
[error] play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:560)
[error] play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:560)
[error] play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$14.apply(Iteratee.scala:537)
[error] play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$14.apply(Iteratee.scala:537)
[error] akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40)
[error] akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397)

这可能与以下方面有关: Slick 3.0-RC3因java.util.concurrent而失败. RejectedExecutionException https://github.com/slick/slick/issues/1183

This may be related to: Slick 3.0-RC3 fails with java.util.concurrent.RejectedExecutionException https://github.com/slick/slick/issues/1183

但是这些都没有解决方案(至少有效) 我曾尝试在规格中添加顺序"标志,但这没做任何事情

However none of these have any solutions (that work at least) I have tried adding the "sequential" flag to my specs but that didn't do anything

推荐答案

问题可能是由于为每个测试套件(规格)重新创建了Play应用所引起的,如

The problem is likely caused by the play app being re-created for every test suite (spec), as described here. In short, objects don't get re-created, and thus dbConfig inside your Groups remains, but is "stale" during the second test.

一种快速而肮脏的解决方法是最初不获取一次dbConfig,而是为每个操作重新获取它:

A quick and dirty workaround is to not get dbConfig once initially, but re-grab it for every operation:

object Groups {
  val groups = TableQuery[GroupTableDef]

  // note this is a function now
  def dbConfig() = DatabaseConfigProvider.get[JdbcProfile](Play.current)

  def add(group: Group): Future[Int] = {
    dbConfig().db.run(groups += group)
  }
}

这显然不是理想的性能,但是由于数据库操作无论如何往往很昂贵,因此重新夺回成本可能不会带来太大的负担.

This is obviously not ideal performance-wise, but since database operations tend to be expensive anyway, this re-grabbing cost might not carry too much weight.

这篇关于在规范“从java.util.concurrent.ThreadPoolExecutor拒绝的任务slick.backend.DatabaseComponent"中播放Slick异常.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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