Skip to content

Commit

Permalink
refactor(db): inject doobie.transactor instead of config
Browse files Browse the repository at this point in the history
  • Loading branch information
yoshinorin committed Jun 18, 2024
1 parent f2efc42 commit ab41433
Show file tree
Hide file tree
Showing 11 changed files with 62 additions and 24 deletions.
6 changes: 5 additions & 1 deletion src/main/scala/net/yoshinorin/qualtet/Modules.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package net.yoshinorin.qualtet

import cats.effect.IO
import doobie.ConnectionIO
import doobie.util.transactor.Transactor.Aux
import org.typelevel.log4cats.{LoggerFactory => Log4CatsLoggerFactory}
import org.typelevel.log4cats.slf4j.{Slf4jFactory => Log4CatsSlf4jFactory}
import com.github.benmanes.caffeine.cache.{Cache => CaffeineCache, Caffeine}
Expand Down Expand Up @@ -49,13 +50,16 @@ import net.yoshinorin.qualtet.infrastructure.db.doobie.DoobieExecuter
import pdi.jwt.JwtAlgorithm
import java.security.SecureRandom
import java.util.concurrent.TimeUnit
import doobie.util.transactor.Transactor
import net.yoshinorin.qualtet.infrastructure.db.doobie.DoobieTransactor

object Modules {

val config = ApplicationConfig.load
val doobieTransactor: DoobieTransactor[Aux] = summon[DoobieTransactor[Aux]]

given log4catsLogger: Log4CatsLoggerFactory[IO] = Log4CatsSlf4jFactory.create[IO]
given dbContext: DoobieExecuter = new DoobieExecuter(config.db)
given dbContext: DoobieExecuter = new DoobieExecuter(doobieTransactor.make(config.db))
val migrator: Migrator = new Migrator(config.db)

// NOTE: for generate JWT. They are reset when re-boot application.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,43 @@ import scala.concurrent.ExecutionContextExecutor
import cats.implicits.catsSyntaxApplicativeId
import doobie.*
import doobie.implicits.*
import doobie.util.transactor.Transactor.Aux
import cats.effect.*
import cats.effect.IO
import net.yoshinorin.qualtet.actions.{Action, Continue, Done}
import net.yoshinorin.qualtet.config.DBConfig
import net.yoshinorin.qualtet.infrastructure.db.Executer

class DoobieExecuter(config: DBConfig) extends Executer[ConnectionIO, IO] {
class DoobieExecuter(tx: Transactor[IO]) extends Executer[ConnectionIO, IO] {

val executors: ExecutorService = Executors.newCachedThreadPool()
val executionContexts: ExecutionContextExecutor = scala.concurrent.ExecutionContext.fromExecutor(executors)

// NOTE: No-need ContextShift: https://typelevel.org/cats-effect/docs/migration-guide#contextshift
// implicit val cs: ContextShift[IO] = IO.contextShift(executionContexts)

val transactor: Aux[IO, Unit] = Transactor.fromDriverManager[IO](
driver = "org.mariadb.jdbc.Driver",
url = config.url,
user = config.user,
password = config.password,
logHandler = None
)

override def perform[R](action: Action[R]): ConnectionIO[R] = action match {
case continue: Continue[ConnectionIO, R, _] => continue.request.flatMap { t => perform(continue.next(t)) }
case done: Done[R] => done.value.pure[ConnectionIO]
}

override def transact[T](connectionIO: ConnectionIO[T]): IO[T] = connectionIO.transact(transactor)
override def transact[T](connectionIO: ConnectionIO[T]): IO[T] = connectionIO.transact(tx)

override def transact[R](action: Action[R]): IO[R] = transact(perform(action))

override def transact2[T1, T2](ts: (ConnectionIO[(T1, T2)])): IO[T2] = {
for {
r <- ts.transact(transactor)
r <- ts.transact(tx)
} yield r._2
}

override def transact4[T1, T2, T3, T4](ts: (ConnectionIO[(T1, T2, T3, T4)])): IO[T4] = {
for {
r <- ts.transact(transactor)
r <- ts.transact(tx)
} yield r._4
}

override def transact8[T1, T2, T3, T4, T5, T6, T7, T8](ts: (ConnectionIO[(T1, T2, T3, T4, T5, T6, T7, T8)])): IO[T8] = {
for {
r <- ts.transact(transactor)
r <- ts.transact(tx)
} yield r._8
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package net.yoshinorin.qualtet.infrastructure.db.doobie

import cats.effect.IO
import doobie.*
import doobie.util.transactor.Transactor.Aux
import net.yoshinorin.qualtet.config.DBConfig

trait DoobieTransactor[F[G[_], _]] {
def make(config: DBConfig): Transactor[IO]
}

object DoobieTransactor {

given DoobieTransactor: DoobieTransactor[Aux] = {
new DoobieTransactor[Aux] {
override def make(config: DBConfig): Transactor[IO] = {
Transactor.fromDriverManager[IO](
driver = "org.mariadb.jdbc.Driver",
url = config.url,
user = config.user,
password = config.password,
logHandler = None
)
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package net.yoshinorin.qualtet.tasks
import cats.effect.IO
import cats.implicits.catsSyntaxEq
import doobie.ConnectionIO
import doobie.util.transactor.Transactor.Aux
import org.slf4j.LoggerFactory
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import net.yoshinorin.qualtet.domains.authors.{Author, AuthorDisplayName, AuthorName, AuthorRepository, AuthorService, BCryptPassword}
Expand All @@ -12,12 +13,15 @@ import net.yoshinorin.qualtet.syntax.*
import net.yoshinorin.qualtet.domains.authors.ResponseAuthor

import cats.effect.unsafe.implicits.global
import net.yoshinorin.qualtet.infrastructure.db.doobie.DoobieTransactor

object CreateAuthor {

private val logger = LoggerFactory.getLogger(this.getClass)

given dbContext: DoobieExecuter = new DoobieExecuter(config.db)
val doobieTransactor: DoobieTransactor[Aux] = summon[DoobieTransactor[Aux]]

given dbContext: DoobieExecuter = new DoobieExecuter(doobieTransactor.make(config.db))
val authorRepository: AuthorRepository[ConnectionIO] = summon[AuthorRepository[ConnectionIO]]
val authorService = new AuthorService(authorRepository)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import cats.effect.IO
import net.yoshinorin.qualtet.domains.authors.ResponseAuthor
import net.yoshinorin.qualtet.message.Fail.{NotFound, Unauthorized}
import net.yoshinorin.qualtet.Modules.*
import net.yoshinorin.qualtet.Modules
import net.yoshinorin.qualtet.fixture.Fixture.*
import net.yoshinorin.qualtet.infrastructure.db.doobie.DoobieExecuter
import org.scalatest.wordspec.AnyWordSpec
Expand All @@ -12,7 +13,8 @@ import cats.effect.unsafe.implicits.global
// testOnly net.yoshinorin.qualtet.auth.AuthServiceSpec
class AuthServiceSpec extends AnyWordSpec {

given dbContext: DoobieExecuter = new DoobieExecuter(config.db)
val tx = doobieTransactor.make(Modules.config.db)
given dbContext: DoobieExecuter = new DoobieExecuter(tx)

val a: ResponseAuthor = authorService.findByName(author.name).unsafeRunSync().get
val a2: ResponseAuthor = authorService.findByName(author2.name).unsafeRunSync().get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import net.yoshinorin.qualtet.domains.robots.Attributes
import net.yoshinorin.qualtet.domains.series.*
import net.yoshinorin.qualtet.fixture.Fixture.*
import net.yoshinorin.qualtet.infrastructure.db.doobie.DoobieExecuter
import net.yoshinorin.qualtet.Modules
import net.yoshinorin.qualtet.Modules.*
import org.scalatest.wordspec.AnyWordSpec
import org.scalatest.BeforeAndAfterAll
Expand All @@ -15,7 +16,8 @@ import org.scalatest.Ignore
@Ignore // TODO: write testcode when implement delete feature
class ContentSerializingServiceSpec extends AnyWordSpec with BeforeAndAfterAll {

given dbContext: DoobieExecuter = new DoobieExecuter(config.db)
val tx = doobieTransactor.make(Modules.config.db)
given dbContext: DoobieExecuter = new DoobieExecuter(tx)

val requestSeries: RequestSeries = RequestSeries(
title = "Content Serializing Service Spec",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import net.yoshinorin.qualtet.domains.contents.{Path, RequestContent}
import net.yoshinorin.qualtet.domains.robots.Attributes
import net.yoshinorin.qualtet.fixture.Fixture.*
import net.yoshinorin.qualtet.infrastructure.db.doobie.DoobieExecuter
import net.yoshinorin.qualtet.Modules
import net.yoshinorin.qualtet.Modules.*
import org.scalatest.wordspec.AnyWordSpec
import org.scalatest.BeforeAndAfterAll
Expand All @@ -13,7 +14,8 @@ import cats.effect.unsafe.implicits.global
// testOnly net.yoshinorin.qualtet.domains.contentTaggings.ContentTaggingServiceSpec
class ContentTaggingServiceSpec extends AnyWordSpec with BeforeAndAfterAll {

given dbContext: DoobieExecuter = new DoobieExecuter(config.db)
val tx = doobieTransactor.make(Modules.config.db)
given dbContext: DoobieExecuter = new DoobieExecuter(tx)

val requestContents: List[RequestContent] = {
List(1, 2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import net.yoshinorin.qualtet.domains.contents.Path
import net.yoshinorin.qualtet.domains.series.{RequestSeries, SeriesName}
import net.yoshinorin.qualtet.fixture.Fixture.*
import net.yoshinorin.qualtet.infrastructure.db.doobie.DoobieExecuter
import net.yoshinorin.qualtet.Modules
import net.yoshinorin.qualtet.Modules.*
import org.scalatest.wordspec.AnyWordSpec
import org.scalatest.BeforeAndAfterAll
Expand All @@ -13,7 +14,8 @@ import cats.effect.unsafe.implicits.global
// testOnly net.yoshinorin.qualtet.domains.SeriesServiceSpec
class SeriesServiceSpec extends AnyWordSpec with BeforeAndAfterAll {

given dbContext: DoobieExecuter = new DoobieExecuter(config.db)
val tx = doobieTransactor.make(Modules.config.db)
given dbContext: DoobieExecuter = new DoobieExecuter(tx)

val requestSeries: List[RequestSeries] = List(
RequestSeries(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package net.yoshinorin.qualtet.domains.tags
import net.yoshinorin.qualtet.domains.contents.Path
import net.yoshinorin.qualtet.fixture.Fixture.*
import net.yoshinorin.qualtet.infrastructure.db.doobie.DoobieExecuter
import net.yoshinorin.qualtet.Modules
import net.yoshinorin.qualtet.Modules.*
import org.scalatest.wordspec.AnyWordSpec
import org.scalatest.BeforeAndAfterAll
Expand All @@ -13,7 +14,8 @@ import cats.effect.unsafe.implicits.global
// testOnly net.yoshinorin.qualtet.domains.TagServiceSpec
class TagServiceSpec extends AnyWordSpec with BeforeAndAfterAll {

given dbContext: DoobieExecuter = new DoobieExecuter(config.db)
val tx = doobieTransactor.make(Modules.config.db)
given dbContext: DoobieExecuter = new DoobieExecuter(tx)

val requestContents = makeRequestContents(10, "tagService")

Expand Down
3 changes: 2 additions & 1 deletion src/test/scala/net/yoshinorin/qualtet/fixture/Fixture.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ object Fixture {
val p: String = Modules.config.http.port.toString()
val host = Uri.unsafeFromString(s"http://${h}:${p}")

given dbContext: DoobieExecuter = new DoobieExecuter(Modules.config.db)
val tx = Modules.doobieTransactor.make(Modules.config.db)
given dbContext: DoobieExecuter = new DoobieExecuter(tx)
given log4catsLogger: Log4CatsLoggerFactory[IO] = Log4CatsSlf4jFactory.create[IO]

// TODO: from config for cache options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import cats.effect.unsafe.implicits.global
// testOnly net.yoshinorin.qualtet.infrastructure.db.MigratorSpec
class MigratorSpec extends AnyWordSpec {

given dbContext: DoobieExecuter = new DoobieExecuter(Modules.config.db)
val tx = Modules.doobieTransactor.make(Modules.config.db)
given dbContext: DoobieExecuter = new DoobieExecuter(tx)

"Migrator" should {

Expand Down

0 comments on commit ab41433

Please sign in to comment.