scala-ddd-base provides traits to support for ddd repositories and aggregates.
Add the following to your sbt build (Scala 2.11.x, 2.12.x):
resolvers += "Sonatype OSS Release Repository" at "https://oss.sonatype.org/content/repositories/releases/" val scalaDddBaseVersion = "..." libraryDependencies ++= Seq( "com.github.j5ik2o" %% "scala-ddd-base-core" % scalaDddBaseVersion, // Please set as necessary // "com.github.j5ik2o" %% "scala-ddd-base-slick" % scalaDddBaseVersion, // "com.github.j5ik2o" %% "scala-ddd-base-skinny" % scalaDddBaseVersion, // "com.github.j5ik2o" %% "scala-ddd-base-redis" % scalaDddBaseVersion, // "com.github.j5ik2o" %% "scala-ddd-base-memcached" % scalaDddBaseVersion, // "com.github.j5ik2o" %% "scala-ddd-base-dynamodb" % scalaDddBaseVersion, // "com.github.j5ik2o" %% "scala-ddd-base-memory" % scalaDddBaseVersion )The following provides basic abstract methods.
- AggregateSingleReader
- AggregateSingleWriter
- AggregateMultiReader
- AggregateMultiWriter
- AggregateSingleSoftDeletable
- AggregateSingleHardDeletable
- AggregateMultiSoftDeletable
- AggregateMultiHardDeletable
The following provides an implementation for each ORM/KVS.
- AggregateSingleReadFeature
- AggregateSingleWriteFeature
- AggregateMultiReadFeature
- AggregateMultiWriteFeature
- AggregateSingleSoftDeleteFeature
- AggregateSingleHardDeleteFeature
- AggregateMultiSoftDeleteFeature
- AggregateMultiHardDeleteFeature
The supported ORM/KVS/Cache is below.
- Slick(JDBC)
- SkinnyORM(JDBC)
- Redis(reactive-redis)
- Memcached(reactive-memcached)
- DynamoDB(reactive-aws-dynamodb)
- Memory(Guava Cache)
Please mix in the core and support traits to your implementation. Slick, SkinnyORM, Memcached, Redis, Memory etc. You can also choose the implementation as you like.
trait UserAccountRepository[M[_]] extends AggregateSingleReader[M] with AggregateMultiReader[M] with AggregateSingleWriter[M] with AggregateMultiWriter[M] with AggregateSingleSoftDeletable[M] with AggregateMultiSoftDeletable[M] { override type IdType = UserAccountId override type AggregateType = UserAccount } object UserAccountRepository { type OnRedis[A] = ReaderT[Task, RedisConnection, A] type OnMemcached[A] = ReaderT[Task, MemcachedConnection, A] type OnDynamoDB[A] = Task[A] type OnMemory[A] = Task[A] type BySlick[A] = Task[A] type BySkinny[A] = ReaderT[Task, DBSession, A] type ByFree[A] = Free[UserRepositoryDSL, A] def bySlick(profile: JdbcProfile, db: JdbcProfile#Backend#Database): UserAccountRepository[BySlick] = new UserAccountRepositoryBySlick(profile, db) def bySkinny: UserAccountRepository[BySkinny] = new UserAccountRepositoryBySkinny def onRedis( expireDuration: Duration )(implicit actorSystem: ActorSystem): UserAccountRepository[OnRedis] = new UserAccountRepositoryOnRedis(expireDuration) def onMemcached( expireDuration: Duration )(implicit actorSystem: ActorSystem): UserAccountRepository[OnMemcached] = new UserAccountRepositoryOnMemcached(expireDuration) def onDynamoDB(dynamoDbAsyncClient: DynamoDbAsyncClient): UserAccountRepository[OnDynamoDB] = new UserAccountRepositoryOnDynamoDB(DynamoDBTaskClientV2(DynamoDBAsyncClientV2(underlying)) def onMemory(minSize: Option[Int] = None, maxSize: Option[Int] = None, expireDuration: Option[Duration] = None, concurrencyLevel: Option[Int] = None, maxWeight: Option[Int] = None): UserAccountRepository[OnMemory] = new UserAccountRepositoryOnMemory(minSize, maxSize, expireDuration, concurrencyLevel, maxWeight) }- for Slick3
val userAccountRepository: UserAccountRepository[BySlick] = UserAccountRepository.bySlick(dbConfig.profile, dbConfig.db) val resultTask: Task[UserAccount] = for { _ <- userAccountRepository.store(userAccount) result <- userAccountRepository.resolveBy(userAccount.id) } yield result val resultFuture: Future[UserAccount] = resultTask.runToFuture- for SkinnyORM
val userAccountRepository: UserAccountRepository[BySkinny] = UserAccountRepository.bySkinny val resultTask: Task[UserAccount] = for { _ <- userAccountRepository.store(userAccount) result <- userAccountRepository.resolveBy(userAccount.id) } yield result val resultFuture: Future[UserAccount] = resultTask.run(AutoSession).runToFuture- for Memcached
val userAccountRepository: UserAccountRepository[OnMemcached] = UserAccountRepository.onMemcached(expireDuration = 5 minutes) val resultFuture: Future[UserAccount] = connectionPool .withConnectionF { con => (for { _ <- userAccountRepository.store(userAccount) r <- userAccountRepository.resolveById(userAccount.id) } yield r).run(con) } .runToFuture- for Redis
val userAccountRepository: UserAccountRepository[OnRedis] = UserAccountRepository.onRedis(expireDuration = 5 minutes) val resultFuture: Future[UserAccount] = connectionPool .withConnectionF { con => (for { _ <- userAccountRepository.store(userAccount) r <- userAccountRepository.resolveById(userAccount.id) } yield r).run(con) } .runToFuture- for DynamoDB
val userAccountRepository: UserAccountRepository[OnDynamoDB] = UserAccountRepository.onDynamoDB(dynamoDbAsyncClient) val resultFuture: Future[UserAccount] = (for { _ <- userAccountRepository.store(userAccount) r <- userAccountRepository.resolveById(userAccount.id) } yield r).runToFuture- for Memory(Guava Cache)
val userAccountRepository: UserAccountRepository[OnMemory] = UserAccountRepository.onMemory(expireAfterWrite = Some(5 minutes)) val resultFuture: Future[UserAccount] = (for { _ <- repository.store(userAccount) r <- repository.resolveById(userAccount.id) } yield r).runToFuture- for Free
val free: UserAccountRepository[ByFree] = UserAccountRepositoryByFree val program: Free[UserRepositoryDSL, UserAccount] = for { _ <- free.store(userAccount) result <- free.resolveById(userAccount.id) } yield result val slick = UserAccountRepository.bySlick(dbConfig.profile, dbConfig.db) val resultTask: Task[UserAccount] = UserAccountRepositoryOnFree.evaluate(slick)(program) val resultFuture: Future[UserAccount] = evalResult.runToFuture // if evaluation by skinny // val skinny = UserAccountRepository.bySkinny // val resultTask: Task[UserAccount] = UserAccountRepositoryOnFree.evaluate(skinny)(program) // val resultFuture: Future[UserAccount] = evalResult.run(AutoSession).runToFuture