From 65eb777de01c5747336d791b69628852f8b36f12 Mon Sep 17 00:00:00 2001 From: Ben Fradet Date: Mon, 4 May 2020 10:25:38 +0200 Subject: [PATCH] Update scalafmt-core to 2.5.1 --- .scalafmt.conf | 2 +- build.sbt | 2 +- debug/shared/src/main/scala/debug.scala | 94 +++++----- debug/shared/src/main/scala/document.scala | 92 +++++----- project/ProjectPlugin.scala | 20 +-- project/plugins.sbt | 24 +-- shared/src/main/scala/cache.scala | 4 +- shared/src/main/scala/execution.scala | 4 +- shared/src/main/scala/fetch.scala | 163 ++++++++---------- .../src/test/scala/FetchBatchingTests.scala | 21 +-- .../src/test/scala/FetchReportingTests.scala | 6 +- shared/src/test/scala/FetchTests.scala | 142 +++++++-------- shared/src/test/scala/TestHelper.scala | 55 +++--- 13 files changed, 301 insertions(+), 328 deletions(-) diff --git a/.scalafmt.conf b/.scalafmt.conf index 48617446..8751e73e 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,4 +1,4 @@ -version = 2.4.2 +version = 2.5.1 style = defaultWithAlign maxColumn = 100 diff --git a/build.sbt b/build.sbt index 66d7b792..546ee859 100644 --- a/build.sbt +++ b/build.sbt @@ -1,6 +1,6 @@ import sbtcrossproject.CrossPlugin.autoImport.{crossProject, CrossType} -lazy val checkScalafmt = "+scalafmtCheck; +scalafmtSbtCheck;" +lazy val checkScalafmt = "+scalafmtCheckAll; +scalafmtSbtCheck;" lazy val checkDocs = "+docs/mdoc;" lazy val checkJSTests = "+fetchJS/test; +debugJS/test;" lazy val checkJVMTests = diff --git a/debug/shared/src/main/scala/debug.scala b/debug/shared/src/main/scala/debug.scala index 28a6fc62..4e8d0136 100644 --- a/debug/shared/src/main/scala/debug.scala +++ b/debug/shared/src/main/scala/debug.scala @@ -52,23 +52,26 @@ object debug { }) } yield lastR - def showLog(log: Log): Document = log.rounds match { - case Nil => Document.empty - case _ => { - val duration: Option[Long] = for { - firstRound <- log.rounds.headOption - firstRequestStart <- firstRequest(firstRound) - lastRound <- log.rounds.lastOption - lastRequestEnd <- lastRequest(lastRound) - } yield lastRequestEnd - firstRequestStart - val durationDoc = - duration.fold(Document.empty: Document)((d: Long) => - Document.text("Fetch execution") :: showDuration(d) + def showLog(log: Log): Document = + log.rounds match { + case Nil => Document.empty + case _ => + val duration: Option[Long] = for { + firstRound <- log.rounds.headOption + firstRequestStart <- firstRequest(firstRound) + lastRound <- log.rounds.lastOption + lastRequestEnd <- lastRequest(lastRound) + } yield lastRequestEnd - firstRequestStart + val durationDoc = + duration.fold(Document.empty: Document)((d: Long) => + Document.text("Fetch execution") :: showDuration(d) + ) + + durationDoc :/: Document.nest( + 2, + pile(log.rounds.mapWithIndex((r, i) => showRound(r, i + 1))) ) - - durationDoc :/: Document.nest(2, pile(log.rounds.mapWithIndex((r, i) => showRound(r, i + 1)))) } - } def showRound(r: Round, n: Int): Document = { val roundDuration = for { @@ -85,12 +88,15 @@ object debug { ) } - def showRequest(r: Request): Document = r.request match { - case FetchOne(id, d) => - Document.text(s"[Fetch one] From `${d.name}` with id ${id}") :: showDuration(r.duration) - case Batch(ids, d) => - Document.text(s"[Batch] From `${d.name}` with ids ${ids.toList}") :: showDuration(r.duration) - } + def showRequest(r: Request): Document = + r.request match { + case FetchOne(id, d) => + Document.text(s"[Fetch one] From `${d.name}` with id ${id}") :: showDuration(r.duration) + case Batch(ids, d) => + Document.text(s"[Batch] From `${d.name}` with ids ${ids.toList}") :: showDuration( + r.duration + ) + } def showMissing(d: Data[_, _], ids: List[_]): Document = Document.text(s"`${d.name}` missing identities ${ids}") @@ -98,30 +104,36 @@ object debug { def showRoundCount(err: FetchException): Document = Document.text(s", fetch interrupted after ${err.log.rounds.size} rounds") - def showException(err: FetchException): Document = err match { - case MissingIdentity(id, q, log) => - Document - .text(s"[ERROR] Identity with id `${id}` for data source `${q.data.name}` not found") :: showRoundCount( - err - ) - case UnhandledException(exc, log) => - Document - .text(s"[ERROR] Unhandled `${exc.getClass.getName}`: '${exc.getMessage}'") :: showRoundCount( - err - ) - } + def showException(err: FetchException): Document = + err match { + case MissingIdentity(id, q, log) => + Document + .text( + s"[ERROR] Identity with id `${id}` for data source `${q.data.name}` not found" + ) :: showRoundCount( + err + ) + case UnhandledException(exc, log) => + Document + .text( + s"[ERROR] Unhandled `${exc.getClass.getName}`: '${exc.getMessage}'" + ) :: showRoundCount( + err + ) + } /* Given a [[fetch.env.Log]], describe it with a human-readable string. */ def describe(log: Log): String = string(showLog(log)) /* Given a [[Throwable]], describe it with a human-readable string. */ - def describe(err: Throwable): String = err match { - case fe: FetchException => - string( - showException(fe) :/: - Document.nest(2, showLog(fe.log)) - ) - case _ => string(Document.text("Unexpected exception")) - } + def describe(err: Throwable): String = + err match { + case fe: FetchException => + string( + showException(fe) :/: + Document.nest(2, showLog(fe.log)) + ) + case _ => string(Document.text("Unexpected exception")) + } } diff --git a/debug/shared/src/main/scala/document.scala b/debug/shared/src/main/scala/document.scala index 998d806a..cbb68216 100644 --- a/debug/shared/src/main/scala/document.scala +++ b/debug/shared/src/main/scala/document.scala @@ -45,26 +45,27 @@ abstract class Document { def format(width: Int, writer: Writer) { type FmtState = (Int, Boolean, Document) - def fits(w: Int, state: List[FmtState]): Boolean = state match { - case _ if w < 0 => - false - case List() => - true - case (_, _, DocNil) :: z => - fits(w, z) - case (i, b, DocCons(h, t)) :: z => - fits(w, (i, b, h) :: (i, b, t) :: z) - case (_, _, DocText(t)) :: z => - fits(w - t.length(), z) - case (i, b, DocNest(ii, d)) :: z => - fits(w, (i + ii, b, d) :: z) - case (_, false, DocBreak) :: z => - fits(w - 1, z) - case (_, true, DocBreak) :: z => - true - case (i, _, DocGroup(d)) :: z => - fits(w, (i, false, d) :: z) - } + def fits(w: Int, state: List[FmtState]): Boolean = + state match { + case _ if w < 0 => + false + case List() => + true + case (_, _, DocNil) :: z => + fits(w, z) + case (i, b, DocCons(h, t)) :: z => + fits(w, (i, b, h) :: (i, b, t) :: z) + case (_, _, DocText(t)) :: z => + fits(w - t.length(), z) + case (i, b, DocNest(ii, d)) :: z => + fits(w, (i + ii, b, d) :: z) + case (_, false, DocBreak) :: z => + fits(w - 1, z) + case (_, true, DocBreak) :: z => + true + case (i, _, DocGroup(d)) :: z => + fits(w, (i, false, d) :: z) + } def spaces(n: Int) { var rem = n @@ -72,33 +73,34 @@ abstract class Document { if (rem >= 8) { writer write " "; rem -= 8 } if (rem >= 4) { writer write " "; rem -= 4 } if (rem >= 2) { writer write " "; rem -= 2 } - if (rem == 1) { writer write " " } + if (rem == 1) writer write " " } - def fmt(k: Int, state: List[FmtState]): Unit = state match { - case List() => () - case (_, _, DocNil) :: z => - fmt(k, z) - case (i, b, DocCons(h, t)) :: z => - fmt(k, (i, b, h) :: (i, b, t) :: z) - case (i, _, DocText(t)) :: z => - writer write t - fmt(k + t.length(), z) - case (i, b, DocNest(ii, d)) :: z => - fmt(k, (i + ii, b, d) :: z) - case (i, true, DocBreak) :: z => - writer write "\n" - spaces(i) - fmt(i, z) - case (i, false, DocBreak) :: z => - writer write " " - fmt(k + 1, z) - case (i, b, DocGroup(d)) :: z => - val fitsFlat = fits(width - k, (i, false, d) :: z) - fmt(k, (i, !fitsFlat, d) :: z) - case _ => - () - } + def fmt(k: Int, state: List[FmtState]): Unit = + state match { + case List() => () + case (_, _, DocNil) :: z => + fmt(k, z) + case (i, b, DocCons(h, t)) :: z => + fmt(k, (i, b, h) :: (i, b, t) :: z) + case (i, _, DocText(t)) :: z => + writer write t + fmt(k + t.length(), z) + case (i, b, DocNest(ii, d)) :: z => + fmt(k, (i + ii, b, d) :: z) + case (i, true, DocBreak) :: z => + writer write "\n" + spaces(i) + fmt(i, z) + case (i, false, DocBreak) :: z => + writer write " " + fmt(k + 1, z) + case (i, b, DocGroup(d)) :: z => + val fitsFlat = fits(width - k, (i, false, d) :: z) + fmt(k, (i, !fitsFlat, d) :: z) + case _ => + () + } fmt(0, (0, false, DocGroup(this)) :: Nil) } diff --git a/project/ProjectPlugin.scala b/project/ProjectPlugin.scala index 97f71c88..49de3604 100644 --- a/project/ProjectPlugin.scala +++ b/project/ProjectPlugin.scala @@ -67,14 +67,14 @@ object ProjectPlugin extends AutoPlugin { lazy val examplesSettings = Seq( libraryDependencies ++= Seq( - "io.circe" %% "circe-generic" % "0.13.0", - "org.tpolecat" %% "doobie-core" % "0.9.0", - "org.tpolecat" %% "doobie-h2" % "0.9.0", - "org.tpolecat" %% "atto-core" % "0.7.2", - "org.http4s" %% "http4s-blaze-client" % "0.21.3", - "org.http4s" %% "http4s-circe" % "0.21.3", - "redis.clients" % "jedis" % "2.9.0", - "io.monix" %% "monix" % "3.0.0" + "io.circe" %% "circe-generic" % "0.13.0", + "org.tpolecat" %% "doobie-core" % "0.9.0", + "org.tpolecat" %% "doobie-h2" % "0.9.0", + "org.tpolecat" %% "atto-core" % "0.7.2", + "org.http4s" %% "http4s-blaze-client" % "0.21.3", + "org.http4s" %% "http4s-circe" % "0.21.3", + "redis.clients" % "jedis" % "2.9.0", + "io.monix" %% "monix" % "3.0.0" ) ) ++ commonCrossDependencies } @@ -91,8 +91,8 @@ object ProjectPlugin extends AutoPlugin { case _ => withStripedLinter }) :+ "-language:higherKinds" }, - addCompilerPlugin("org.typelevel" % "kind-projector" % "0.11.0" cross CrossVersion.full), - addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1"), + addCompilerPlugin("org.typelevel" % "kind-projector" % "0.11.0" cross CrossVersion.full), + addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1"), scalacOptions := Seq( "-unchecked", "-deprecation", diff --git a/project/plugins.sbt b/project/plugins.sbt index 5a78ab55..c53989b9 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,12 +1,12 @@ -addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.5.3") -addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.0.1") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.3.4") -addSbtPlugin("com.47deg" % "sbt-microsites" % "1.2.0") -addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.1") -addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.1.5") -addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.6.0") -addSbtPlugin("com.alejandrohdezma" %% "sbt-github" % "0.8.0") -addSbtPlugin("com.alejandrohdezma" % "sbt-github-header" % "0.8.0") -addSbtPlugin("com.alejandrohdezma" % "sbt-github-mdoc" % "0.8.0") -addSbtPlugin("com.alejandrohdezma" % "sbt-mdoc-toc" % "0.2") +addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.5.3") +addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.0.1") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.3.4") +addSbtPlugin("com.47deg" % "sbt-microsites" % "1.2.0") +addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.1") +addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.1.5") +addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.6.0") +addSbtPlugin("com.alejandrohdezma" %% "sbt-github" % "0.8.0") +addSbtPlugin("com.alejandrohdezma" % "sbt-github-header" % "0.8.0") +addSbtPlugin("com.alejandrohdezma" % "sbt-github-mdoc" % "0.8.0") +addSbtPlugin("com.alejandrohdezma" % "sbt-mdoc-toc" % "0.2") diff --git a/shared/src/main/scala/cache.scala b/shared/src/main/scala/cache.scala index fd173f17..f6ca9cb5 100644 --- a/shared/src/main/scala/cache.scala +++ b/shared/src/main/scala/cache.scala @@ -33,8 +33,8 @@ trait DataCache[F[_]] { def insert[I, A](i: I, v: A, data: Data[I, A]): F[DataCache[F]] - def bulkInsert[I, A](vs: List[(I, A)], data: Data[I, A])( - implicit M: Monad[F] + def bulkInsert[I, A](vs: List[(I, A)], data: Data[I, A])(implicit + M: Monad[F] ): F[DataCache[F]] = { vs.foldLeftM(this) { case (acc, (i, v)) => diff --git a/shared/src/main/scala/execution.scala b/shared/src/main/scala/execution.scala index 29ee3273..6149b185 100644 --- a/shared/src/main/scala/execution.scala +++ b/shared/src/main/scala/execution.scala @@ -21,8 +21,8 @@ import cats.effect._ import cats.syntax.all._ private object FetchExecution { - def parallel[F[_], A](effects: NonEmptyList[F[A]])( - implicit CF: Concurrent[F] + def parallel[F[_], A](effects: NonEmptyList[F[A]])(implicit + CF: Concurrent[F] ): F[NonEmptyList[A]] = effects .traverse(CF.start(_)) diff --git a/shared/src/main/scala/fetch.scala b/shared/src/main/scala/fetch.scala index 8deff30c..d05babeb 100644 --- a/shared/src/main/scala/fetch.scala +++ b/shared/src/main/scala/fetch.scala @@ -154,72 +154,70 @@ object `package` { private def combineRequests[F[_]: Monad]( x: BlockedRequest[F], y: BlockedRequest[F] - ): BlockedRequest[F] = (x.request, y.request) match { - case (a @ FetchOne(aId, ds), b @ FetchOne(anotherId, _)) => - if (aId == anotherId) { - val newRequest = FetchOne(aId, ds) - val newResult = x.result.flatMap(() => y.result) - BlockedRequest(newRequest, newResult) - } else { + ): BlockedRequest[F] = + (x.request, y.request) match { + case (a @ FetchOne(aId, ds), b @ FetchOne(anotherId, _)) => + if (aId == anotherId) { + val newRequest = FetchOne(aId, ds) + val newResult = x.result.flatMap(() => y.result) + BlockedRequest(newRequest, newResult) + } else { + val combined = combineIdentities(a, b) + val newRequest = Batch(combined, ds) + val newResult = CombinationSuspend((r: FetchStatus) => + r match { + case FetchDone(m: Map[Any, Any]) => + val xResult = m.get(aId).map(FetchDone(_)).getOrElse(FetchMissing()) + val yResult = m.get(anotherId).map(FetchDone(_)).getOrElse(FetchMissing()) + CombinationBarrier(() => x.result, xResult) + .flatMap(() => CombinationBarrier(() => y.result, yResult)) + + case FetchMissing() => + x.result.flatMap(() => y.result) + } + ) + BlockedRequest(newRequest, newResult) + } + + case (a @ FetchOne(oneId, ds), b @ Batch(anotherIds, _)) => val combined = combineIdentities(a, b) val newRequest = Batch(combined, ds) val newResult = CombinationSuspend((r: FetchStatus) => r match { - case FetchDone(m: Map[Any, Any]) => { - val xResult = m.get(aId).map(FetchDone(_)).getOrElse(FetchMissing()) - val yResult = m.get(anotherId).map(FetchDone(_)).getOrElse(FetchMissing()) - CombinationBarrier(() => x.result, xResult) - .flatMap(() => CombinationBarrier(() => y.result, yResult)) - } + case FetchDone(m: Map[Any, Any]) => + val oneResult = m.get(oneId).map(FetchDone(_)).getOrElse(FetchMissing()) + CombinationBarrier(() => x.result, oneResult) + .flatMap(() => y.result) case FetchMissing() => x.result.flatMap(() => y.result) } ) - BlockedRequest(newRequest, newResult) - } - case (a @ FetchOne(oneId, ds), b @ Batch(anotherIds, _)) => - val combined = combineIdentities(a, b) - val newRequest = Batch(combined, ds) - val newResult = CombinationSuspend((r: FetchStatus) => - r match { - case FetchDone(m: Map[Any, Any]) => { - val oneResult = m.get(oneId).map(FetchDone(_)).getOrElse(FetchMissing()) - CombinationBarrier(() => x.result, oneResult) - .flatMap(() => y.result) - } + BlockedRequest(newRequest, newResult) - case FetchMissing() => - x.result.flatMap(() => y.result) - } - ) + case (a @ Batch(manyId, ds), b @ FetchOne(oneId, _)) => + val combined = combineIdentities(a, b) + val newRequest = Batch(combined, ds) + val newResult = CombinationSuspend((r: FetchStatus) => + r match { + case FetchDone(m: Map[Any, Any]) => + val oneResult = m.get(oneId).map(FetchDone(_)).getOrElse(FetchMissing()) + CombinationBarrier(() => y.result, oneResult) + .flatMap(() => x.result) - BlockedRequest(newRequest, newResult) - - case (a @ Batch(manyId, ds), b @ FetchOne(oneId, _)) => - val combined = combineIdentities(a, b) - val newRequest = Batch(combined, ds) - val newResult = CombinationSuspend((r: FetchStatus) => - r match { - case FetchDone(m: Map[Any, Any]) => { - val oneResult = m.get(oneId).map(FetchDone(_)).getOrElse(FetchMissing()) - CombinationBarrier(() => y.result, oneResult) - .flatMap(() => x.result) + case FetchMissing() => + x.result.flatMap(() => y.result) } + ) + BlockedRequest(newRequest, newResult) - case FetchMissing() => - x.result.flatMap(() => y.result) - } - ) - BlockedRequest(newRequest, newResult) - - case (a @ Batch(manyId, ds), b @ Batch(otherId, _)) => - val combined = combineIdentities(a, b) - val newRequest = Batch(combined, ds) - val newResult = x.result.flatMap(() => y.result) - BlockedRequest(newRequest, newResult) - } + case (a @ Batch(manyId, ds), b @ Batch(otherId, _)) => + val combined = combineIdentities(a, b) + val newRequest = Batch(combined, ds) + val newResult = x.result.flatMap(() => y.result) + BlockedRequest(newRequest, newResult) + } /* A map from datasource identities to (data source, blocked request) pairs used to group requests to the same data source. */ private[fetch] final case class RequestMap[F[_]]( @@ -230,18 +228,16 @@ object `package` { private def combineRequestMaps[F[_]: Monad](x: RequestMap[F], y: RequestMap[F]): RequestMap[F] = RequestMap( x.m.foldLeft(y.m) { - case (acc, (dsId, (ds, blocked))) => { + case (acc, (dsId, (ds, blocked))) => val combined = acc .get(dsId) .fold( (ds, blocked) )({ - case (d, req) => { + case (d, req) => (d, combineRequests(blocked, req)) - } }) acc.updated(dsId, combined) - } } ) @@ -435,8 +431,7 @@ object `package` { private[fetch] class FetchRunner[F[_]](private val dummy: Boolean = true) extends AnyVal { def apply[A]( fa: Fetch[F, A] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[A] = @@ -445,8 +440,7 @@ object `package` { def apply[A]( fa: Fetch[F, A], cache: DataCache[F] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[A] = @@ -464,8 +458,7 @@ object `package` { private[fetch] class FetchRunnerLog[F[_]](private val dummy: Boolean = true) extends AnyVal { def apply[A]( fa: Fetch[F, A] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[(Log, A)] = @@ -474,8 +467,7 @@ object `package` { def apply[A]( fa: Fetch[F, A], cache: DataCache[F] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[(Log, A)] = @@ -494,8 +486,7 @@ object `package` { private[fetch] class FetchRunnerCache[F[_]](private val dummy: Boolean = true) extends AnyVal { def apply[A]( fa: Fetch[F, A] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[(DataCache[F], A)] = @@ -504,8 +495,7 @@ object `package` { def apply[A]( fa: Fetch[F, A], cache: DataCache[F] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[(DataCache[F], A)] = @@ -524,8 +514,7 @@ object `package` { private[fetch] class FetchRunnerAll[F[_]](private val dummy: Boolean = true) extends AnyVal { def apply[A]( fa: Fetch[F, A] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[(Log, DataCache[F], A)] = @@ -534,8 +523,7 @@ object `package` { def apply[A]( fa: Fetch[F, A], cache: DataCache[F] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[(Log, DataCache[F], A)] = @@ -555,8 +543,7 @@ object `package` { fa: Fetch[F, A], cache: Ref[F, DataCache[F]], log: Option[Ref[F, Log]] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[A] = @@ -583,8 +570,7 @@ object `package` { rs: RequestMap[F], cache: Ref[F, DataCache[F]], log: Option[Ref[F, Log]] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[Unit] = { @@ -600,12 +586,13 @@ object `package` { }) ) performedRequests = requests.foldLeft(List.empty[Request])(_ ++ _) - _ <- if (performedRequests.isEmpty) Applicative[F].unit - else - log match { - case Some(l) => l.modify((oldE) => (oldE.append(Round(performedRequests)), oldE)) - case None => Applicative[F].unit - } + _ <- + if (performedRequests.isEmpty) Applicative[F].unit + else + log match { + case Some(l) => l.modify((oldE) => (oldE.append(Round(performedRequests)), oldE)) + case None => Applicative[F].unit + } } yield () } @@ -614,8 +601,7 @@ object `package` { ds: DataSource[F, Any, Any], cache: Ref[F, DataCache[F]], log: Option[Ref[F, Log]] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[List[Request]] = @@ -631,8 +617,7 @@ object `package` { putResult: CombinationTailRec[F], cache: Ref[F, DataCache[F]], log: Option[Ref[F, Log]] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[List[Request]] = @@ -678,8 +663,7 @@ object `package` { putResult: CombinationTailRec[F], cache: Ref[F, DataCache[F]], log: Option[Ref[F, Log]] - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[List[Request]] = @@ -731,8 +715,7 @@ object `package` { ds: DataSource[F, Any, Any], batchSize: Int, e: BatchExecution - )( - implicit + )(implicit C: Concurrent[F], T: Timer[F] ): F[BatchedRequest] = { diff --git a/shared/src/test/scala/FetchBatchingTests.scala b/shared/src/test/scala/FetchBatchingTests.scala index befc7256..7c670702 100644 --- a/shared/src/test/scala/FetchBatchingTests.scala +++ b/shared/src/test/scala/FetchBatchingTests.scala @@ -110,12 +110,11 @@ class FetchBatchingTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(1, 2, 3, 4, 5) log.rounds.size shouldEqual 1 totalFetched(log.rounds) shouldEqual 5 totalBatches(log.rounds) shouldEqual 3 - } }) .unsafeToFuture } @@ -127,12 +126,11 @@ class FetchBatchingTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(1, 2, 3, 4, 5) log.rounds.size shouldEqual 1 totalFetched(log.rounds) shouldEqual 5 totalBatches(log.rounds) shouldEqual 3 - } }) .unsafeToFuture } @@ -145,12 +143,11 @@ class FetchBatchingTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(1, 2, 3, 4, 5) log.rounds.size shouldEqual 1 totalFetched(log.rounds) shouldEqual 5 + 5 totalBatches(log.rounds) shouldEqual 3 + 3 - } }) .unsafeToFuture } @@ -163,12 +160,11 @@ class FetchBatchingTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(1, 2, 3, 4, 5) log.rounds.size shouldEqual 1 totalFetched(log.rounds) shouldEqual 5 + 5 totalBatches(log.rounds) shouldEqual 3 + 3 - } }) .unsafeToFuture } @@ -180,12 +176,11 @@ class FetchBatchingTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(1, 2, 3) log.rounds.size shouldEqual 1 totalFetched(log.rounds) shouldEqual 3 totalBatches(log.rounds) shouldEqual 2 - } }) .unsafeToFuture } @@ -197,12 +192,11 @@ class FetchBatchingTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(1, 2, 3) log.rounds.size shouldEqual 1 totalFetched(log.rounds) shouldEqual 3 totalBatches(log.rounds) shouldEqual 2 - } }) .unsafeToFuture } @@ -222,9 +216,8 @@ class FetchBatchingTests extends FetchSpec { ) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual ids.map(_.toString) - } }) .unsafeToFuture } diff --git a/shared/src/test/scala/FetchReportingTests.scala b/shared/src/test/scala/FetchReportingTests.scala index b46f19c9..9ef976f5 100644 --- a/shared/src/test/scala/FetchReportingTests.scala +++ b/shared/src/test/scala/FetchReportingTests.scala @@ -92,7 +92,7 @@ class FetchReportingTests extends FetchSpec { "Single fetches combined with traverse are run in one round" in { def fetch[F[_]: ConcurrentEffect] = for { - manies <- many(3) // round 1 + manies <- many(3) // round 1 ones <- manies.traverse(one[F]) // round 2 } yield ones @@ -126,9 +126,9 @@ class FetchReportingTests extends FetchSpec { def anotherFetch[F[_]: ConcurrentEffect] = for { - a <- one(2) // round 1 (batched) + a <- one(2) // round 1 (batched) m <- many(4) // round 2 - c <- one(3) // round 3 (deduplicated) + c <- one(3) // round 3 (deduplicated) } yield c def fetch[F[_]: ConcurrentEffect] = diff --git a/shared/src/test/scala/FetchTests.scala b/shared/src/test/scala/FetchTests.scala index 1ca83662..e50e24c3 100644 --- a/shared/src/test/scala/FetchTests.scala +++ b/shared/src/test/scala/FetchTests.scala @@ -149,10 +149,9 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual (1, 2) log.rounds.size shouldEqual 2 - } }) .unsafeToFuture } @@ -167,10 +166,9 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(0, 1, 2) log.rounds.size shouldEqual 2 - } }) .unsafeToFuture } @@ -182,12 +180,11 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(1, 2, 3) log.rounds.size shouldEqual 1 totalFetched(log.rounds) shouldEqual 3 totalBatches(log.rounds) shouldEqual 1 - } }) .unsafeToFuture } @@ -200,14 +197,13 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual sources log.rounds.size shouldEqual 1 log.rounds.head.queries.size shouldEqual 1 log.rounds.head.queries.head.request should matchPattern { case Batch(NonEmptyList(1, List(2)), _) => } - } }) .unsafeToFuture } @@ -219,11 +215,10 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual (1, List(0, 1, 2)) log.rounds.size shouldEqual 1 log.rounds.head.queries.size shouldEqual 2 - } }) .unsafeToFuture } @@ -235,11 +230,10 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual (1, List(0, 1, 2)) log.rounds.size shouldEqual 1 totalBatches(log.rounds) shouldEqual 0 - } }) .unsafeToFuture } @@ -251,11 +245,10 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual ((1, List(0, 1)), 3) log.rounds.size shouldEqual 1 totalBatches(log.rounds) shouldEqual 0 - } }) .unsafeToFuture } @@ -273,12 +266,11 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual ((1, (2, 3)), 4) log.rounds.size shouldEqual 1 totalBatches(log.rounds) shouldEqual 1 totalFetched(log.rounds) shouldEqual 4 - } }) .unsafeToFuture } @@ -306,12 +298,11 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual ((1, 2), 3) log.rounds.size shouldEqual 2 totalBatches(log.rounds) shouldEqual 2 totalFetched(log.rounds) shouldEqual 5 - } }) .unsafeToFuture } @@ -335,12 +326,11 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual (1, 2) log.rounds.size shouldEqual 2 totalBatches(log.rounds) shouldEqual 2 totalFetched(log.rounds) shouldEqual 4 - } }) .unsafeToFuture } @@ -348,15 +338,15 @@ class FetchTests extends FetchSpec { "Every level of sequenced concurrent fetches is batched" in { def aFetch[F[_]: ConcurrentEffect] = for { - a <- List(2, 3, 4).traverse(one[F]) // round 1 - b <- List(0, 1).traverse(many[F]) // round 2 + a <- List(2, 3, 4).traverse(one[F]) // round 1 + b <- List(0, 1).traverse(many[F]) // round 2 c <- List(9, 10, 11).traverse(one[F]) // round 3 } yield c def anotherFetch[F[_]: ConcurrentEffect] = for { - a <- List(5, 6, 7).traverse(one[F]) // round 1 - b <- List(2, 3).traverse(many[F]) // round 2 + a <- List(5, 6, 7).traverse(one[F]) // round 1 + b <- List(2, 3).traverse(many[F]) // round 2 c <- List(12, 13, 14).traverse(one[F]) // round 3 } yield c @@ -369,12 +359,11 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual ((List(9, 10, 11), List(12, 13, 14)), List(15, 16, 17)) log.rounds.size shouldEqual 3 totalBatches(log.rounds) shouldEqual 3 totalFetched(log.rounds) shouldEqual 9 + 4 + 6 - } }) .unsafeToFuture } @@ -385,12 +374,11 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual (1, 3) log.rounds.size shouldEqual 1 totalBatches(log.rounds) shouldEqual 1 totalFetched(log.rounds) shouldEqual 2 - } }) .unsafeToFuture } @@ -402,11 +390,10 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(1, 2, 3, 4, 5) log.rounds.size shouldEqual 1 totalBatches(log.rounds) shouldEqual 2 - } }) .unsafeToFuture } @@ -418,12 +405,11 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(1, 2, 1) log.rounds.size shouldEqual 1 totalBatches(log.rounds) shouldEqual 1 totalFetched(log.rounds) shouldEqual 2 - } }) .unsafeToFuture } @@ -435,11 +421,10 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(1, 2, 3) log.rounds.size shouldEqual 1 totalBatches(log.rounds) shouldEqual 1 - } }) .unsafeToFuture } @@ -451,11 +436,10 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(1, 2, 1) log.rounds.size shouldEqual 1 totalFetched(log.rounds) shouldEqual 2 - } }) .unsafeToFuture } @@ -470,11 +454,10 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual List(1, 2, 1) log.rounds.size shouldEqual 1 totalFetched(log.rounds) shouldEqual 2 - } }) .unsafeToFuture } @@ -492,11 +475,10 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual (1, 5) log.rounds.size shouldEqual 1 totalFetched(log.rounds) shouldEqual 2 - } }) .unsafeToFuture } @@ -519,10 +501,9 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual 2 totalFetched(log.rounds) shouldEqual 3 - } }) .unsafeToFuture } @@ -543,11 +524,10 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual 2 log.rounds.size shouldEqual 1 totalFetched(log.rounds) shouldEqual 3 - } }) .unsafeToFuture } @@ -565,20 +545,20 @@ class FetchTests extends FetchSpec { _ <- one(1) } yield aOne + anotherOne - def cache[F[_]: ConcurrentEffect] = InMemoryCache.from[F, Int, Int]( - (One, 1) -> 1, - (One, 2) -> 2, - (One, 3) -> 3 - ) + def cache[F[_]: ConcurrentEffect] = + InMemoryCache.from[F, Int, Int]( + (One, 1) -> 1, + (One, 2) -> 2, + (One, 3) -> 3 + ) val io = Fetch.runLog[IO](fetch, cache) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual 2 totalFetched(log.rounds) shouldEqual 0 log.rounds.size shouldEqual 0 - } }) .unsafeToFuture } @@ -596,11 +576,12 @@ class FetchTests extends FetchSpec { _ <- one(1) } yield aOne + anotherOne - def cache[F[_]: ConcurrentEffect] = InMemoryCache.from[F, Int, Int]( - (One, 1) -> 1, - (One, 2) -> 2, - (One, 3) -> 3 - ) + def cache[F[_]: ConcurrentEffect] = + InMemoryCache.from[F, Int, Int]( + (One, 1) -> 1, + (One, 2) -> 2, + (One, 3) -> 3 + ) val io = Fetch.run[IO](fetch, cache) @@ -620,18 +601,18 @@ class FetchTests extends FetchSpec { _ <- one(1) } yield aOne + anotherOne - def cache[F[_]: ConcurrentEffect] = InMemoryCache.from[F, Int, Int]( - (One, 1) -> 1, - (One, 2) -> 2, - (One, 3) -> 3 - ) + def cache[F[_]: ConcurrentEffect] = + InMemoryCache.from[F, Int, Int]( + (One, 1) -> 1, + (One, 2) -> 2, + (One, 3) -> 3 + ) val io = Fetch.runCache[IO](fetch, cache) io.map({ - case (c, result) => { + case (c, result) => result shouldEqual 2 - } }) .unsafeToFuture } @@ -652,9 +633,8 @@ class FetchTests extends FetchSpec { val io = Fetch.runCache[IO](fetch) io.map({ - case (c, result) => { + case (c, result) => result shouldEqual 2 - } }) .unsafeToFuture } @@ -684,11 +664,10 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch, forgetfulCache) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual 2 log.rounds.size shouldEqual 7 totalFetched(log.rounds) shouldEqual 7 - } }) .unsafeToFuture } @@ -709,11 +688,10 @@ class FetchTests extends FetchSpec { val io = Fetch.runLog[IO](fetch, forgetfulCache) io.map({ - case (log, result) => { + case (log, result) => result shouldEqual 2 log.rounds.size shouldEqual 8 totalFetched(log.rounds) shouldEqual 10 - } }) .unsafeToFuture } @@ -739,9 +717,10 @@ class FetchTests extends FetchSpec { } "Data sources with errors won't fail if they're cached" in { - def cache[F[_]: ConcurrentEffect] = InMemoryCache.from[F, Never, Int]( - (Never, Never()) -> 1 - ) + def cache[F[_]: ConcurrentEffect] = + InMemoryCache.from[F, Never, Int]( + (Never, Never()) -> 1 + ) val io = Fetch.run[IO](never, cache) io.map(_ shouldEqual 1).unsafeToFuture @@ -840,17 +819,18 @@ class FetchTests extends FetchSpec { object MaybeMissing extends Data[MaybeMissing, Int] { def name = "Maybe Missing" - implicit def source[F[_]: ConcurrentEffect] = new DataSource[F, MaybeMissing, Int] { - override def data = MaybeMissing + implicit def source[F[_]: ConcurrentEffect] = + new DataSource[F, MaybeMissing, Int] { + override def data = MaybeMissing - override def CF = ConcurrentEffect[F] + override def CF = ConcurrentEffect[F] - override def fetch(id: MaybeMissing): F[Option[Int]] = - if (id.id % 2 == 0) - CF.pure(None) - else - CF.pure(Option(id.id)) - } + override def fetch(id: MaybeMissing): F[Option[Int]] = + if (id.id % 2 == 0) + CF.pure(None) + else + CF.pure(Option(id.id)) + } } diff --git a/shared/src/test/scala/TestHelper.scala b/shared/src/test/scala/TestHelper.scala index 96ad5216..39be52d9 100644 --- a/shared/src/test/scala/TestHelper.scala +++ b/shared/src/test/scala/TestHelper.scala @@ -28,19 +28,20 @@ object TestHelper { object One extends Data[Int, Int] { def name = "One" - def source[F[_]: ConcurrentEffect]: DataSource[F, Int, Int] = new DataSource[F, Int, Int] { - override def data = One + def source[F[_]: ConcurrentEffect]: DataSource[F, Int, Int] = + new DataSource[F, Int, Int] { + override def data = One - override def CF = ConcurrentEffect[F] + override def CF = ConcurrentEffect[F] - override def fetch(id: Int): F[Option[Int]] = - CF.pure(Option(id)) + override def fetch(id: Int): F[Option[Int]] = + CF.pure(Option(id)) - override def batch(ids: NonEmptyList[Int]): F[Map[Int, Int]] = - CF.pure( - ids.toList.map((v) => (v, v)).toMap - ) - } + override def batch(ids: NonEmptyList[Int]): F[Map[Int, Int]] = + CF.pure( + ids.toList.map((v) => (v, v)).toMap + ) + } } def one[F[_]: ConcurrentEffect](id: Int): Fetch[F, Int] = @@ -66,19 +67,20 @@ object TestHelper { object AnotherOne extends Data[Int, Int] { def name = "Another one" - def source[F[_]: ConcurrentEffect]: DataSource[F, Int, Int] = new DataSource[F, Int, Int] { - override def data = AnotherOne + def source[F[_]: ConcurrentEffect]: DataSource[F, Int, Int] = + new DataSource[F, Int, Int] { + override def data = AnotherOne - override def CF = ConcurrentEffect[F] + override def CF = ConcurrentEffect[F] - override def fetch(id: Int): F[Option[Int]] = - CF.pure(Option(id)) + override def fetch(id: Int): F[Option[Int]] = + CF.pure(Option(id)) - override def batch(ids: NonEmptyList[Int]): F[Map[Int, Int]] = - CF.pure( - ids.toList.map((v) => (v, v)).toMap - ) - } + override def batch(ids: NonEmptyList[Int]): F[Map[Int, Int]] = + CF.pure( + ids.toList.map((v) => (v, v)).toMap + ) + } } def anotherOne[F[_]: ConcurrentEffect](id: Int): Fetch[F, Int] = @@ -89,14 +91,15 @@ object TestHelper { object Never extends Data[Never, Int] { def name = "Never" - def source[F[_]: ConcurrentEffect]: DataSource[F, Never, Int] = new DataSource[F, Never, Int] { - override def data = Never + def source[F[_]: ConcurrentEffect]: DataSource[F, Never, Int] = + new DataSource[F, Never, Int] { + override def data = Never - override def CF = ConcurrentEffect[F] + override def CF = ConcurrentEffect[F] - override def fetch(id: Never): F[Option[Int]] = - CF.pure(None: Option[Int]) - } + override def fetch(id: Never): F[Option[Int]] = + CF.pure(None: Option[Int]) + } } def never[F[_]: ConcurrentEffect]: Fetch[F, Int] =