So this would be my "improved" version which closes the databases which
will possibly run out-of-sync:
object TxnHelper {
trait Resource extends Closeable with ExternalDecider
private class Decider(var instances: List[Resource])
extends ExternalDecider {
def shouldCommit(implicit txn: InTxnEnd): Boolean =
instances match {
case single :: Nil => single.shouldCommit
case _ => commitAll(instances, Nil)
}
@tailrec
private def commitAll(remain: List[Resource], done: List[Resource])
(implicit txn: InTxnEnd): Boolean =
remain match {
case head :: tail =>
if (head.shouldCommit) {
commitAll(tail, head :: done)
} else {
if (done.nonEmpty) {
Console.err.println(s"Resource $head failed to commit"
+ " transaction.")
done.foreach { r =>
Console.err.println(s"Closing $r as a precaution."
+ " The system must be re-opened prior to further"
+ " use.")
try {
r.close()
} catch {
case NonFatal(e) => e.printStackTrace()
}
}
}
false
}
case _ => true
}
}
private val decider = TxnLocal[Decider]()
def addResource(resource: Resource)(implicit tx: InTxn): Unit =
if (decider.isInitialized) {
decider().instances ::= resource
} else {
val d = new Decider(resource :: Nil)
ScalaTxn.setExternalDecider(d)
decider() = d