Skip to content

Instantly share code, notes, and snippets.

@eishay
Created May 2, 2016 22:50
Show Gist options
  • Save eishay/6e9791c722cc1c17e8c98922d8e265e2 to your computer and use it in GitHub Desktop.
Save eishay/6e9791c722cc1c17e8c98922d8e265e2 to your computer and use it in GitHub Desktop.
// this allows us to replace the database session implementation in tests
// and check when sessions are being obtained
@ImplementedBy(classOf[SlickSessionProviderImpl])
trait SlickSessionProvider {
def createReadOnlySession(handle: SlickDatabase): Session
def createReadWriteSession(handle: SlickDatabase): Session
}
@Singleton
class SlickSessionProviderImpl extends SlickSessionProvider {
def createReadOnlySession(handle: SlickDatabase): Session = {
handle.createSession().forParameters(rsConcurrency = ResultSetConcurrency.ReadOnly)
}
def createReadWriteSession(handle: SlickDatabase): Session = {
handle.createSession().forParameters(rsConcurrency = ResultSetConcurrency.Updatable)
}
}
class Database @Inject() (
val db: DataBaseComponent,
val sessionProvider: SlickSessionProvider
) extends Logging {
import DBSession._
val dialect: DatabaseDialect[_] = db.dialect
def readOnlyAsync[T](f: ROSession => T): Future[T] = future { readOnly(f) }
def readWriteAsync[T](f: RWSession => T): Future[T] = future { readWrite(f) }
def readWriteAsync[T](attempts: Int)(f: RWSession => T): Future[T] = future { readWrite(attempts)(f) }
def readOnly[T](f: ROSession => T): T = {
var s: Option[Session] = None
val ro = new ROSession({
s = Some(sessionProvider.createReadOnlySession(db.handle))
s.get
})
try f(ro) finally s.foreach(_.close())
}
def readWrite[T](f: RWSession => T): T = {
val s = sessionProvider.createReadWriteSession(db.handle)
try {
s.withTransaction {
f(new RWSession(s))
}
} finally s.close()
}
def readWrite[T](attempts: Int)(f: RWSession => T): T = {
1 to attempts - 1 foreach { attempt =>
try {
return readWrite(f)
} catch {
case ex: MySQLIntegrityConstraintViolationException =>
throw ex
case t: SQLException =>
val throwableName = t.getClass.getSimpleName
log.warn(s"Failed ($throwableName) readWrite transaction attempt $attempt of $attempts")
}
}
readWrite(f)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment