Play Framework 2.6,Postgresql。 Jooq作为db访问库。
运行测试时,我正在
org.postgresql.util.PSQLException:致命:抱歉,客户太多了 已经
这是一个提供jooq的dsl上下文的辅助类:
@Singleton
class Db @Inject() (val db: Database, system: ActorSystem) {
val databaseContext: ExecutionContext = system.dispatchers.lookup("contexts.database")
def query[A](block: DSLContext => A): Future[A] = Future {
db.withConnection { connection: Connection =>
val dsl = DSL.using(connection, SQLDialect.POSTGRES_9_4)
block(dsl)
}
}(databaseContext)
def withTransaction[A](block: DSLContext => A): Future[A] = Future {
db.withTransaction { connection: Connection =>
val dsl: DSLContext = DSL.using(connection, SQLDialect.POSTGRES_9_4)
block(dsl)
}
}(databaseContext)
}
我在这样的存储库中使用这个助手类:
db.query { dsl =>
val records = dsl
.selectFrom(USERS)
.where(...)
...
}
}
application.conf
db.default.driver="org.postgresql.Driver"
db.default.url="jdbc:postgresql://localhost/postgres?user=postgres"
...
contexts {
database {
executor = "thread-pool-executor"
throughput = 1
thread-pool-executor {
fixed-pool-size = 9
}
}
}
...
build.sbt
...
libraryDependencies += jdbc
libraryDependencies += "org.jooq" % "jooq" % "3.10.5"
libraryDependencies += "org.jooq" % "jooq-codegen-maven" % "3.10.5"
libraryDependencies += "org.jooq" % "jooq-meta" % "3.10.5"
libraryDependencies += "org.postgresql" % "postgresql" % "42.1.4"
...
我所有测试的基本特征:
class BaseFeatureSpec extends FeatureSpec
with GivenWhenThen
with GuiceOneServerPerSuite
with Matchers
with WsScalaTestClient
with BeforeAndAfterEach
with MockitoSugar {
override def fakeApplication(): Application =
new GuiceApplicationBuilder()
.overrides(bind[EmailService].to(classOf[EmailServiceStub]))
.build()
def config: Configuration = fakeApplication().configuration
def actorSystem: ActorSystem = fakeApplication().actorSystem
val db: Db = app.injector.instanceOf[Db]
val wsClient: WSClient = app.injector.instanceOf[WSClient]
val myPublicAddress = s"localhost:$port"
private val injector = fakeApplication().injector
def truncateDbOnEachRun = true
override protected def beforeEach(): Unit = {
if (truncateDbOnEachRun) {
truncateDb
}
}
protected def truncateDb = {
await(db.withTransaction { dsl =>
... truncate all dbs...
})
}
}
我的postgresql实例的max_connections是100。
我注意到,在运行测试时,我发现在每次测试之前几次创建了池:
[info] application - Creating Pool for datasource 'default'
[info] application - Creating Pool for datasource 'default'
[info] application - Creating Pool for datasource 'default'
[info] application - Creating Pool for datasource 'default'
我收到too many connections
错误后。
请帮忙。
答案 0 :(得分:0)
看起来您使用默认类型的调度程序,尝试添加type = PinnedDispatcher,用于io类型调度程序,如下所示。
$(PackageOutputAbsolutePath)$(PackageId).$(PackageVersion).nupkg
你可以从中找到细节 https://doc.akka.io/docs/akka/2.5/dispatchers.html
答案 1 :(得分:0)
我发现了这个问题:
override def fakeApplication(): Application =
new GuiceApplicationBuilder()
.overrides(bind[EmailService].to(classOf[EmailServiceStub]))
.build()
每次访问app.injector.instanceOf[Db]
时都会创建新的应用程序实例(因为它是方法),这就是为什么我有这么多application - Creating Pool for datasource 'default'
个日志的原因。
我已将def
替换为val
override val fakeApplication(): Application =
new GuiceApplicationBuilder()
.overrides(bind[EmailService].to(classOf[EmailServiceStub]))
.build()
它运作正常。