在我的ScalaTest套件结束时,我需要做一些数据库清理。
清理本身是Future
。该套件不会调用super.afterAll()
,这会使套件使用的某些资源(如Web浏览器和数据库连接)等待处理。
以下是相关的代码:
override def afterAll():Unit={
var cleanUpsInProgress = true
DB.cleanUpDeletedSegments(db).onComplete{case _ =>
cleanUpsInProgress = false
}
while(cleanUpsInProgress){}
db.close()
aggregatesDB.close()
super.afterAll()
}
和
def cleanUpDeletedSegments(implicit db:ADMPDB):Future[Int]={
db.run{
segments.filter(_.deleted === 1).delete
}
}
我已经调试了一段时间,并且得知结论它甚至没有在将来的onComplete
回调中处理代码。即使我用存根Future.successfull(1)
替换Slick的数据库操作,我仍然有一切未决并且super.afterAll()
未被调用。
可能我做了一些愚蠢的错事?你能帮忙吗?
注意:我也认为我需要在这里使用这个丑陋的var
和while
循环,因为否则主线程将完成,启动套件运行的框架将关闭JVM。也许我错了,所以听听一些评论会很棒。
-------------------------- UPDATE -------------------- -
泰勒的解决方案有效。但是当我flatMap
再次进行asynch清理(我实际上需要做)时,问题又是一样的。以下代码冻结,不会调用super.afterAll
:
override def afterAll():Unit={
val cleanUp = DB.cleanUpDeletedSegments(db).flatMap(_ => DB.cleanUpDeletedSegmentGroups(db))
Await.result(cleanUp, 6 seconds)
db.close()
aggregatesDB.close()
super.afterAll()
}
Await.result
也不会抛出TimeoutException,而是从我看不到正常完成的内容。有什么想法吗?
只有在我为每个未来按顺序使用Await.result
时,它才有效:
override def afterAll():Unit={
val cleanUpSegments = DB.cleanUpDeletedSegments(db)
Await.result(cleanUpSegments, 3 seconds)
val cleanUpSegmentGroups = DB.cleanUpDeletedSegmentGroups(db)
Await.result(cleanUpSegmentGroups, 3 seconds)
db.close()
aggregatesDB.close()
super.afterAll()
}
答案 0 :(得分:3)
await
清理完成Future
可能更容易:
import scala.concurrent.Await
import scala.concurrent.duration._
override def afterAll() ={
val future = DB.cleanUpDeletedSegments(db)
Await.result(future, 2 minutes)
aggregatesDB.close()
super.afterAll()
}
您可以将超时设置为合理的
答案 1 :(得分:2)
使用@Tyler的解决方案。您的解决方案无效,因为您使用了来自多个线程的非易失性变量cleanupInProgress
。