I currently have a set of Data Access Objects named with the convention *SlickRepo
. So for instance, UserSlickRepo
, DistributionSlickRepo
, ContentSlickRepo
, etc...
Each of these Repos have methods on them that basically follow this convention:
trait SomethingRepoImpl extends SomethingRepo {
val somethingRepo: SomethingRepo = new SomethingRepoImpl
class SomethingRepoImpl extends SomethingRepo with MySlickDatastore {
def getSomething(id: UUID): Either[SomethingNotFoundError, Something] = {
getDatabase withDynSession {
// Slick stuff
}
}
def createSomething .....
}
}
Now up at a Service level, we bake in this repo class and we have methods that look like this:
trait SomethingServiceImpl extends SomethingService {
dep: SomethingRepo with SomethingElseRepo =>
val somethingService = new SomethingServiceImpl
class SomethingServiceImpl extends SomethingService {
def createSomethingGood(): Either[SomeError, (Something, SomethingElse)] = {
(dep.somethingRepo.createSomething, dep.somethingElseRepo.createSomethingElse)
}
}
}
We now desire to have createSomethingGood
actually run the two repo methods within a transaction. Since all the Slick stuff is locked up in the Slick specific Repo methods, what's the best way to do this? I'm not opposed to having Slick-specific code in my *ServiceImpl
classes (I mean weird, but ok), however does that mean I have to change my Repo classes to remove the getDatabase withDynSession
type code all together and instead pass in a session from the service layer? To me, that just seems... wrong.
Maybe there is another way. I haven't tried it myself, but the idea is that you could have a Session wrapper that actually gets passed to the Repo.
That wrapper would have to be created at the service layer, but you can abstract the specific implementation on a companion object so the service layer doesn't actually deal with Slick, but rather something like
I hope this helps, I'll add more to the response if I get the change to give it a try myself.