Created
May 2, 2016 22:50
-
-
Save eishay/6e9791c722cc1c17e8c98922d8e265e2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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