From 9c22c10bd40ffb43e5ef69616e851e3efc05b3bb Mon Sep 17 00:00:00 2001 From: Katrix Date: Wed, 21 Nov 2018 19:17:56 +0000 Subject: [PATCH] Update doobie to 0.6 (#710) --- app/db/impl/service/OreModelService.scala | 46 ++++++++++++++++++----- app/db/query/DoobieOreProtocol.scala | 46 +++++++++++++---------- build.sbt | 2 +- test/DbSpec.scala | 19 ++++++++-- 4 files changed, 80 insertions(+), 33 deletions(-) diff --git a/app/db/impl/service/OreModelService.scala b/app/db/impl/service/OreModelService.scala index 937e6d179..fb7f7520a 100644 --- a/app/db/impl/service/OreModelService.scala +++ b/app/db/impl/service/OreModelService.scala @@ -1,16 +1,18 @@ package db.impl.service +import java.util.concurrent.Executors import javax.inject.{Inject, Singleton} -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.duration._ import play.api.db.slick.DatabaseConfigProvider +import play.api.inject.ApplicationLifecycle import db.impl.OrePostgresDriver import ore.{OreConfig, OreEnv} -import cats.effect.IO +import cats.effect.{ContextShift, IO} import doobie._ import doobie.implicits._ import doobie.util.transactor.Strategy @@ -26,8 +28,10 @@ import slick.jdbc.{JdbcDataSource, JdbcProfile} class OreModelService @Inject()( env: OreEnv, config: OreConfig, - db: DatabaseConfigProvider -) extends OreDBOs(OrePostgresDriver, env, config) { + db: DatabaseConfigProvider, + lifecycle: ApplicationLifecycle +)(implicit ec: ExecutionContext) + extends OreDBOs(OrePostgresDriver, env, config) { val Logger = play.api.Logger("Database") @@ -35,12 +39,34 @@ class OreModelService @Inject()( lazy val DB = db.get[JdbcProfile] override lazy val DefaultTimeout: Duration = this.config.app.dbDefaultTimeout - implicit lazy val xa: Transactor.Aux[IO, JdbcDataSource] = Transactor[IO, JdbcDataSource]( - DB.db.source, - source => IO(source.createConnection()), - KleisliInterpreter[IO].ConnectionInterpreter, - Strategy.default - ) + implicit lazy val xa: Transactor.Aux[IO, JdbcDataSource] = { + implicit val cs: ContextShift[IO] = IO.contextShift(ec) + + val connectExec = Executors.newFixedThreadPool(32) + val transactExec = Executors.newCachedThreadPool + val connectEC = ExecutionContext.fromExecutor(connectExec) + val transactEC = ExecutionContext.fromExecutor(transactExec) + + //We stop them separately so one having problems stopping doesn't hinder the other one + lifecycle.addStopHook { () => + Future { + connectExec.shutdown() + } + } + + lifecycle.addStopHook { () => + Future { + transactExec.shutdown() + } + } + + Transactor[IO, JdbcDataSource]( + DB.db.source, + source => cs.evalOn(connectEC)(IO(source.createConnection())), + KleisliInterpreter[IO](transactEC).ConnectionInterpreter, + Strategy.default + ) + } override def runDBIO[R](action: driver.api.DBIO[R]): Future[R] = DB.db.run(action) diff --git a/app/db/query/DoobieOreProtocol.scala b/app/db/query/DoobieOreProtocol.scala index f376fe95f..fd756bd79 100644 --- a/app/db/query/DoobieOreProtocol.scala +++ b/app/db/query/DoobieOreProtocol.scala @@ -28,26 +28,26 @@ import org.postgresql.util.PGobject trait DoobieOreProtocol { implicit def objectIdMeta[A](implicit tt: TypeTag[ObjId[A]]): Meta[ObjId[A]] = - Meta[Long].xmap(ObjId.apply[A], _.value) - implicit val objectTimestampMeta: Meta[ObjectTimestamp] = Meta[Timestamp].xmap(ObjectTimestamp.apply, _.value) + Meta[Long].timap(ObjId.apply[A])(_.value) + implicit val objectTimestampMeta: Meta[ObjectTimestamp] = Meta[Timestamp].timap(ObjectTimestamp.apply)(_.value) - implicit val jsonMeta: Meta[JsValue] = Meta + implicit val jsonMeta: Meta[JsValue] = Meta.Advanced .other[PGobject]("jsonb") - .xmap[JsValue]( - o => Option(o).map(a => Json.parse(a.getValue)).orNull, - a => - Option(a).map { a => - val o = new PGobject - o.setType("jsonb") - o.setValue(a.toString()) - o - }.orNull - ) + .timap[JsValue] { o => + Option(o).map(a => Json.parse(a.getValue)).orNull + } { a => + Option(a).map { a => + val o = new PGobject + o.setType("jsonb") + o.setValue(a.toString()) + o + }.orNull + } def enumeratumMeta[V: TypeTag, E <: ValueEnumEntry[V]: TypeTag]( enum: ValueEnum[V, E] )(implicit meta: Meta[V]): Meta[E] = - meta.xmap[E](enum.withValue, _.value) + meta.timap[E](enum.withValue)(_.value) implicit val colorMeta: Meta[Color] = enumeratumMeta(Color) implicit val tagColorMeta: Meta[TagColor] = enumeratumMeta(TagColor) @@ -66,9 +66,9 @@ trait DoobieOreProtocol { implicit val trustMeta: Meta[Trust] = enumeratumMeta(Trust) implicit val reviewStateMeta: Meta[ReviewState] = enumeratumMeta(ReviewState) - implicit val langMeta: Meta[Lang] = Meta[String].xmap(Lang.apply, _.toLocale.toLanguageTag) + implicit val langMeta: Meta[Lang] = Meta[String].timap(Lang.apply)(_.toLocale.toLanguageTag) implicit val inetStringMeta: Meta[InetString] = - Meta[InetAddress].xmap(address => InetString(address.toString), str => InetAddress.getByName(str.value)) + Meta[InetAddress].timap(address => InetString(address.toString))(str => InetAddress.getByName(str.value)) implicit val roleCategoryMeta: Meta[RoleCategory] = pgEnumString[RoleCategory]( name = "ROLE_CATEGORY", @@ -84,13 +84,21 @@ trait DoobieOreProtocol { } ) + def metaFromGetPut[A](implicit get: Get[A], put: Put[A]): Meta[A] = new Meta(get, put) + implicit val promptArrayMeta: Meta[List[Prompt]] = - Meta[List[Int]].xmap(_.map(Prompt.withValue), _.map(_.value)) + metaFromGetPut[List[Int]].timap(_.map(Prompt.withValue))(_.map(_.value)) implicit val roleTypeArrayMeta: Meta[List[Role]] = - Meta[List[String]].xmap(_.map(Role.withValue), _.map(_.value)) + metaFromGetPut[List[String]].timap(_.map(Role.withValue))(_.map(_.value)) implicit def unsafeNelMeta[A](implicit listMeta: Meta[List[A]], typeTag: TypeTag[NEL[A]]): Meta[NEL[A]] = - listMeta.xmap(NEL.fromListUnsafe, _.toList) + listMeta.timap(NEL.fromListUnsafe)(_.toList) + + implicit def unsafeNelGet[A](implicit listGet: Get[List[A]], typeTag: TypeTag[NEL[A]]): Get[NEL[A]] = + listGet.tmap(NEL.fromListUnsafe) + + implicit def unsafeNelPut[A](implicit listPut: Put[List[A]], typeTag: TypeTag[NEL[A]]): Put[NEL[A]] = + listPut.tcontramap(_.toList) } object DoobieOreProtocol extends DoobieOreProtocol diff --git a/build.sbt b/build.sbt index 077adf082..fe75f8dab 100755 --- a/build.sbt +++ b/build.sbt @@ -63,7 +63,7 @@ resolvers ++= Seq( "Akka Snapshot Repository".at("http://repo.akka.io/snapshots/") ) -lazy val doobieVersion = "0.5.3" +lazy val doobieVersion = "0.6.0" libraryDependencies ++= Seq(ehcache, ws, guice) diff --git a/test/DbSpec.scala b/test/DbSpec.scala index 914a947a6..aefc98ebe 100644 --- a/test/DbSpec.scala +++ b/test/DbSpec.scala @@ -1,11 +1,14 @@ +import java.util.concurrent.Executors import javax.sql.DataSource +import scala.concurrent.ExecutionContext + import play.api.db.Databases import play.api.db.evolutions.Evolutions import db.query.DoobieOreProtocol -import cats.effect.IO +import cats.effect.{ContextShift, IO} import doobie.Transactor import doobie.scalatest.IOChecker import org.scalatest.{BeforeAndAfterAll, FunSuite, Matchers} @@ -20,11 +23,21 @@ trait DbSpec extends FunSuite with Matchers with IOChecker with BeforeAndAfterAl "password" -> sys.env.getOrElse("DB_PASSWORD", "") ) ) + private lazy val connectExec = Executors.newFixedThreadPool(32) + private lazy val transactExec = Executors.newCachedThreadPool + private lazy val connectEC = ExecutionContext.fromExecutor(connectExec) + private lazy val transactEC = ExecutionContext.fromExecutor(transactExec) + + implicit private val cs: ContextShift[IO] = IO.contextShift(ExecutionContext.global) lazy val transactor: Transactor.Aux[IO, DataSource] = - Transactor.fromDataSource[IO](database.dataSource) + Transactor.fromDataSource[IO](database.dataSource, connectEC, transactEC) override def beforeAll(): Unit = Evolutions.applyEvolutions(database) - override def afterAll(): Unit = database.shutdown() + override def afterAll(): Unit = { + database.shutdown() + connectExec.shutdown() + transactExec.shutdown() + } }