diff --git a/build.sbt b/build.sbt index 5aaff86..c67c8fa 100644 --- a/build.sbt +++ b/build.sbt @@ -131,18 +131,24 @@ Global / onChangedBuildSource := ReloadOnSourceChanges lazy val enforceMimaCompatibility = true // Enable / disable failing CI on binary incompatibilities +lazy val mimaIssueFilters = Seq( + ProblemFilters.exclude[Problem]("zio.query.internal.Continue*"), + ProblemFilters.exclude[Problem]("zio.query.internal.Result*"), + ProblemFilters.exclude[Problem]("zio.query.internal.BlockedRequests*") +) + lazy val enableMimaSettingsJVM = Def.settings( mimaFailOnProblem := enforceMimaCompatibility, mimaPreviousArtifacts := previousStableVersion.value.map(organization.value %% moduleName.value % _).toSet, - mimaBinaryIssueFilters ++= Seq() + mimaBinaryIssueFilters ++= mimaIssueFilters ) lazy val enableMimaSettingsJS = Def.settings( mimaFailOnProblem := enforceMimaCompatibility, mimaPreviousArtifacts := previousStableVersion.value.map(organization.value %%% moduleName.value % _).toSet, - mimaBinaryIssueFilters ++= Seq() + mimaBinaryIssueFilters ++= mimaIssueFilters ) lazy val ciReleaseModeKey = "CI_RELEASE_MODE" diff --git a/zio-query/shared/src/main/scala/zio/query/ZQuery.scala b/zio-query/shared/src/main/scala/zio/query/ZQuery.scala index 654e88c..2cca206 100644 --- a/zio-query/shared/src/main/scala/zio/query/ZQuery.scala +++ b/zio-query/shared/src/main/scala/zio/query/ZQuery.scala @@ -19,7 +19,6 @@ package zio.query import zio._ import zio.query.ZQuery.disabledCache import zio.query.internal._ -import zio.stacktracer.TracingImplicits.disableAutoTrace import java.util.concurrent.atomic.AtomicBoolean import scala.annotation.switch @@ -204,7 +203,13 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result def catchAll[R1 <: R, E2, A1 >: A]( h: E => ZQuery[R1, E2, A1] )(implicit ev: CanFail[E], trace: Trace): ZQuery[R1, E2, A1] = - self.foldQuery[R1, E2, A1](h, ZQuery.succeedNow) + ZQuery { + step.flatMap { + case Result.Blocked(br, c) => Result.blockedExit(br, c.catchAll(h)) + case Result.Fail(e) => e.failureOrCause.fold(h, ZQuery.FailCauseNone).step + case done => Exit.succeed(done.widen) + } + } /** * Recovers from all errors with provided Cause. @@ -212,7 +217,16 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result def catchAllCause[R1 <: R, E2, A1 >: A](h: Cause[E] => ZQuery[R1, E2, A1])(implicit trace: Trace ): ZQuery[R1, E2, A1] = - self.foldCauseQuery[R1, E2, A1](h, ZQuery.succeedNow) + ZQuery { + step.foldCauseZIO( + h(_).step, + { + case Result.Blocked(br, c) => Result.blockedExit(br, c.catchAllCause(h)) + case Result.Fail(e) => h(e).step + case done => Exit.succeed(done.widen) + } + ) + } /** * Recovers from all errors and maps the provided Cause to a ZIO effect @@ -220,7 +234,16 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result def catchAllCauseZIO[R1 <: R, E2, A1 >: A](h: Cause[E] => ZIO[R1, E2, A1])(implicit trace: Trace ): ZQuery[R1, E2, A1] = - foldCauseZIO(h, Exit.succeed) + ZQuery { + step.foldCauseZIO( + h(_).foldCauseZIO(Result.failExit, Result.doneExit), + { + case Result.Blocked(br, c) => Result.blockedExit(br, c.foldCauseZIO(h, Exit.succeed)) + case Result.Fail(e) => h(e).foldCauseZIO(Result.failExit, Result.doneExit) + case done => Exit.succeed(done.widen) + } + ) + } /** * Catches all errors and maps them to a ZIO effect @@ -258,7 +281,7 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result step.flatMap { case Result.Blocked(br, c) => Result.blockedExit(br, c.mapQuery(f)) case Result.Done(a) => f(a).step - case Result.Fail(e) => Result.failExit(e) + case e => Exit.succeed(e.widen) } } @@ -337,7 +360,13 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result ev: CanFail[E], trace: Trace ): ZQuery[R1, E1, B] = - foldCauseQuery(_.failureOrCause.fold(failure, ZQuery.failCause(_)), success) + ZQuery { + step.flatMap { + case Result.Blocked(br, c) => Result.blockedExit(br, c.foldQuery(failure, success)) + case Result.Done(a) => success(a).step + case Result.Fail(e) => e.failureOrCause.fold(failure, ZQuery.FailCauseNone).step + } + } /** * Recovers from errors by accepting one ZIO effect to execute for the case of @@ -347,7 +376,14 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result failure: E => ZIO[R1, E1, B], success: A => ZIO[R1, E1, B] )(implicit trace: Trace): ZQuery[R1, E1, B] = - foldCauseZIO(_.failureOrCause.fold(failure, Exit.failCause), success) + ZQuery { + step.flatMap { + case Result.Blocked(br, c) => Result.blockedExit(br, c.foldZIO(failure, success)) + case Result.Done(a) => success(a).foldCauseZIO(Result.failExit, Result.doneExit) + case Result.Fail(e) => + e.failureOrCause.fold(failure(_).foldCauseZIO(Result.failExit, Result.doneExit), Exit.failCause) + } + } /** * "Zooms in" on the value in the `Left` side of an `Either`, moving the @@ -389,7 +425,7 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result * }}} */ def memoize(implicit trace: Trace): UIO[ZQuery[R, E, A]] = - ZIO.succeed(ZQuery.unsafe.memoize(self)(Unsafe.unsafe, trace)) + ZIO.succeed(ZQuery.unsafe.memoize(self)(Unsafe, trace)) /** * Maps the specified function over the successful result of this query. @@ -433,7 +469,13 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result * Maps the specified function over the failed result of this query. */ def mapError[E1](f: E => E1)(implicit ev: CanFail[E], trace: Trace): ZQuery[R, E1, A] = - mapBoth(f, identity) + ZQuery { + step.flatMap { + case Result.Blocked(br, c) => Result.blockedExit(br, c.mapError(f)) + case Result.Fail(e) => e.failureOrCause.fold(e => Result.failExit(Cause.fail(f(e))), Exit.failCause) + case done => Exit.succeed(done.widen) + } + } /** * Returns a query with its full cause of failure mapped using the specified @@ -441,7 +483,16 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result * original structure of `Cause`. */ def mapErrorCause[E2](h: Cause[E] => Cause[E2])(implicit trace: Trace): ZQuery[R, E2, A] = - mapBothCause(h, ZIO.identityFn) + ZQuery { + step.foldCauseZIO( + e => Result.failExit(h(e)), + { + case Result.Blocked(br, c) => Result.blockedExit(br, c.mapErrorCause(h)) + case Result.Fail(e) => Result.failExit(h(e)) + case done => Exit.succeed(done.widen) + } + ) + } /** * Maps the specified effectual function over the result of this query. @@ -451,7 +502,7 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result step.flatMap { case Result.Blocked(br, c) => Result.blockedExit(br, c.mapZIO(f)) case Result.Done(a) => f(a).foldCauseZIO(Result.failExit, Result.doneExit) - case f: Result.Fail[E1] => Exit.succeed(f) + case f => Exit.succeed(f.widen) } } @@ -480,7 +531,7 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result * specified function to map the error to a `Throwable`. */ def orDieWith(f: E => Throwable)(implicit ev: CanFail[E], trace: Trace): ZQuery[R, Nothing, A] = - foldQuery(e => ZQuery.die(f(e)), a => ZQuery.succeedNow(a)) + catchAll(e => ZQuery.die(f(e))) /** * Provides a layer to this query, which translates it to another level. @@ -518,7 +569,7 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result def provideSomeEnvironment[R0]( f: => Described[ZEnvironment[R0] => ZEnvironment[R]] )(implicit trace: Trace): ZQuery[R0, E, A] = - ZQuery(step.map(_.provideSomeEnvironment(f)).provideSomeEnvironment((r => (f.value(r))))) + ZQuery(step.map(_.provideSomeEnvironment(f)).provideSomeEnvironment(f.value)) /** * Races this query with the specified query, returning the result of the @@ -542,8 +593,8 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result case Continue.Get(io) => Result.blockedExit(blockedRequests, Continue.effect(race(ZQuery.fromZIONow(io), fiber))) } - case Result.Done(value) => fiber.interrupt *> Result.doneExit(value) case Result.Fail(cause) => fiber.join.map(_.mapErrorCause(_ && cause)) + case done => fiber.interrupt.as(done) } ) @@ -672,7 +723,7 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result * Expose the full cause of failure of this query */ def sandbox(implicit trace: Trace): ZQuery[R, Cause[E], A] = - foldCauseQuery(ZQuery.failNow, ZQuery.succeedNow) + catchAllCause(ZQuery.failNow) /** * Companion helper to `sandbox`. Allows recovery, and partial recovery, from @@ -694,7 +745,7 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result e => ZQuery.failNow(Some(e)), ev(_) match { case Some(b) => ZQuery.succeedNow(b) - case None => ZQuery.failNow(None) + case _ => ZQuery.failNow(None) } ) @@ -712,7 +763,7 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result )(implicit ev: A <:< Option[B], trace: Trace): ZQuery[R1, E1, B] = self.flatMap(ev(_) match { case Some(value) => ZQuery.succeedNow(value) - case None => default + case _ => default }) /** @@ -724,7 +775,7 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result self.flatMap { a => ev(a) match { case Some(b) => ZQuery.succeedNow(b) - case None => ZQuery.failNow(e) + case _ => ZQuery.failNow(e) } } @@ -735,14 +786,12 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result */ def summarized[R1 <: R, E1 >: E, B, C]( summary0: ZIO[R1, E1, B] - )(f: (B, B) => C)(implicit trace: Trace): ZQuery[R1, E1, (C, A)] = { - val summary = summary0 + )(f: (B, B) => C)(implicit trace: Trace): ZQuery[R1, E1, (C, A)] = for { - start <- ZQuery.fromZIONow(summary) + start <- ZQuery.fromZIONow(summary0) value <- self - end <- ZQuery.fromZIONow(summary) + end <- ZQuery.fromZIONow(summary0) } yield (f(start, end), value) - } /** * Returns a new query that executes this one and times the execution. @@ -821,7 +870,7 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result * Takes some fiber failures and converts them into errors. */ def unrefine[E1 >: E](pf: PartialFunction[Throwable, E1])(implicit trace: Trace): ZQuery[R, E1, A] = - unrefineWith(pf)(identity) + unrefineWith(pf)(ZIO.identityFn) /** * Takes some fiber failures and converts them into errors. @@ -973,15 +1022,15 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result val br = if (br1.isEmpty) br2 else if (br2.isEmpty) br1 else br1 ++ br2 Result.blocked(br, c1.zipWith(c2)(f)) case Result.Done(b) => Result.blocked(br1, c1.map(a => f(a, b))) - case Result.Fail(e) => Result.fail(e) + case e => e.widen } case Result.Done(a) => that.step.map { case Result.Blocked(br, c) => Result.blocked(br, c.map(b => f(a, b))) case Result.Done(b) => Result.done(f(a, b)) - case Result.Fail(e) => Result.fail(e) + case e => e.widen } - case e: Result.Fail[E1] => Exit.succeed(e) + case e => Exit.succeed(e.widen) } } @@ -1001,8 +1050,8 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result case (Result.Done(a), Result.Blocked(br, c)) => Result.blocked(br, c.map(b => f(a, b))) case (Result.Done(a), Result.Done(b)) => Result.done(f(a, b)) case (Result.Fail(e1), Result.Fail(e2)) => Result.fail(Cause.Both(e1, e2)) - case (Result.Fail(e), _) => Result.fail(e) - case (_, Result.Fail(e)) => Result.fail(e) + case (e: Result.Fail[E1], _) => e + case (_, e: Result.Fail[E1]) => e } } @@ -1024,8 +1073,8 @@ final class ZQuery[-R, +E, +A] private (private val step: ZIO[R, Nothing, Result case (Result.Done(a), Result.Blocked(br, c)) => Result.blocked(br, c.map(b => f(a, b))) case (Result.Done(a), Result.Done(b)) => Result.done(f(a, b)) case (Result.Fail(e1), Result.Fail(e2)) => Result.fail(Cause.Both(e1, e2)) - case (Result.Fail(e), _) => Result.fail(e) - case (_, Result.Fail(e)) => Result.fail(e) + case (e: Result.Fail[E1], _) => e + case (_, e: Result.Fail[E1]) => e } } @@ -1066,7 +1115,7 @@ object ZQuery { bf: BuildFrom[Collection[ZQuery[R, E, A]], A, Collection[A]], trace: Trace ): ZQuery[R, E, Collection[A]] = - foreach(as)(identity) + foreach(as)(ZIO.identityFn) /** * Collects a collection of queries into a query returning a collection of @@ -1074,7 +1123,7 @@ object ZQuery { * pipelined. */ def collectAll[R, E, A](as: Set[ZQuery[R, E, A]])(implicit trace: Trace): ZQuery[R, E, Set[A]] = - foreach(as)(identity) + foreach(as)(ZIO.identityFn) /** * Collects a collection of queries into a query returning a collection of @@ -1082,7 +1131,7 @@ object ZQuery { * pipelined. */ def collectAll[R, E, A: ClassTag](as: Array[ZQuery[R, E, A]])(implicit trace: Trace): ZQuery[R, E, Array[A]] = - foreach(as)(identity) + foreach(as)(ZIO.identityFn) /** * Collects a collection of queries into a query returning a collection of @@ -1090,7 +1139,7 @@ object ZQuery { * pipelined. */ def collectAll[R, E, A](as: Option[ZQuery[R, E, A]])(implicit trace: Trace): ZQuery[R, E, Option[A]] = - foreach(as)(identity) + foreach(as)(ZIO.identityFn) /** * Collects a collection of queries into a query returning a collection of @@ -1100,7 +1149,7 @@ object ZQuery { def collectAll[R, E, A](as: NonEmptyChunk[ZQuery[R, E, A]])(implicit trace: Trace ): ZQuery[R, E, NonEmptyChunk[A]] = - foreach(as)(identity) + foreach(as)(ZIO.identityFn) /** * Collects a collection of queries into a query returning a collection of @@ -1112,14 +1161,14 @@ object ZQuery { bf: BuildFrom[Collection[ZQuery[R, E, A]], A, Collection[A]], trace: Trace ): ZQuery[R, E, Collection[A]] = - foreachBatched(as)(identity) + foreachBatched(as)(ZIO.identityFn) /** * Collects a collection of queries into a query returning a collection of * their results, batching requests to data sources. */ def collectAllBatched[R, E, A](as: Set[ZQuery[R, E, A]])(implicit trace: Trace): ZQuery[R, E, Set[A]] = - foreachBatched(as)(identity) + foreachBatched(as)(ZIO.identityFn) /** * Collects a collection of queries into a query returning a collection of @@ -1128,7 +1177,7 @@ object ZQuery { def collectAllBatched[R, E, A: ClassTag](as: Array[ZQuery[R, E, A]])(implicit trace: Trace ): ZQuery[R, E, Array[A]] = - foreachBatched(as)(identity) + foreachBatched(as)(ZIO.identityFn) /** * Collects a collection of queries into a query returning a collection of @@ -1137,7 +1186,7 @@ object ZQuery { def collectAllBatched[R, E, A](as: NonEmptyChunk[ZQuery[R, E, A]])(implicit trace: Trace ): ZQuery[R, E, NonEmptyChunk[A]] = - foreachBatched(as)(identity) + foreachBatched(as)(ZIO.identityFn) /** * Collects a collection of queries into a query returning a collection of @@ -1149,14 +1198,14 @@ object ZQuery { bf: BuildFrom[Collection[ZQuery[R, E, A]], A, Collection[A]], trace: Trace ): ZQuery[R, E, Collection[A]] = - foreachPar(as)(identity) + foreachPar(as)(ZIO.identityFn) /** * Collects a collection of queries into a query returning a collection of * their results. Requests will be executed in parallel and will be batched. */ def collectAllPar[R, E, A](as: Set[ZQuery[R, E, A]])(implicit trace: Trace): ZQuery[R, E, Set[A]] = - foreachPar(as)(identity) + foreachPar(as)(ZIO.identityFn) /** * Collects a collection of queries into a query returning a collection of @@ -1165,7 +1214,7 @@ object ZQuery { def collectAllPar[R, E, A: ClassTag](as: Array[ZQuery[R, E, A]])(implicit trace: Trace ): ZQuery[R, E, Array[A]] = - foreachPar(as)(identity) + foreachPar(as)(ZIO.identityFn) /** * Collects a collection of queries into a query returning a collection of @@ -1174,7 +1223,7 @@ object ZQuery { def collectAllPar[R, E, A](as: NonEmptyChunk[ZQuery[R, E, A]])(implicit trace: Trace ): ZQuery[R, E, NonEmptyChunk[A]] = - foreachPar(as)(identity) + foreachPar(as)(ZIO.identityFn) /** * Constructs a query that dies with the specified error. @@ -1243,8 +1292,8 @@ object ZQuery { )( f: A => ZQuery[R, E, B] )(implicit bf: BuildFrom[Collection[A], B, Collection[B]], trace: Trace): ZQuery[R, E, Collection[B]] = { - implicit val ct1: ClassTag[A] = anyRefClassTag - implicit val c2: ClassTag[B] = anyRefClassTag + implicit def ct1: ClassTag[A] = anyRefClassTag + implicit def ct2: ClassTag[B] = anyRefClassTag foreachSequentialOuter[R, E, A, B, Collection](as.toArray, mode = Mode.Sequential, bf.fromSpecific(as)(_))(f) } @@ -1315,8 +1364,8 @@ object ZQuery { )( f: A => ZQuery[R, E, B] )(implicit bf: BuildFrom[Collection[A], B, Collection[B]], trace: Trace): ZQuery[R, E, Collection[B]] = { - implicit val ct1: ClassTag[A] = anyRefClassTag - implicit val ct2: ClassTag[B] = anyRefClassTag + implicit def ct1: ClassTag[A] = anyRefClassTag + implicit def ct2: ClassTag[B] = anyRefClassTag foreachSequentialOuter[R, E, A, B, Collection](as.toArray, mode = Mode.Batched, bf.fromSpecific(as)(_))(f) } @@ -1375,7 +1424,7 @@ object ZQuery { case -1 => ZQuery.succeedNow(bf.fromSpecific(as)(Nil)) case 0 => f(as.head).map(v => (bf.newBuilder(as) += v).result()) case _ => - implicit val ct: ClassTag[A] = anyRefClassTag + implicit def ct: ClassTag[A] = anyRefClassTag ZQuery { ZIO .foreachPar(as.toArray)(f(_).step) @@ -1550,15 +1599,15 @@ object ZQuery { ) ) case Right(promise) => - promise.unsafe.poll(Unsafe.unsafe) match { - case None => CachedResult.Pure(Result.blocked(BlockedRequests.empty, Continue(promise))) + promise.unsafe.poll(Unsafe) match { case Some(io: Exit[E, B]) => CachedResult.Pure(Result.fromExit(io)) case Some(io) => CachedResult.Effectful(io.exit.map(Result.fromExit)) + case _ => CachedResult.Pure(Result.blocked(BlockedRequests.empty, Continue(promise))) } } cache match { - case cache: Cache.Default => foldPromise(cache.lookupUnsafe(request)(Unsafe.unsafe)) + case cache: Cache.Default => foldPromise(cache.lookupUnsafe(request)(Unsafe)) case cache => CachedResult.Effectful(cache.lookup(request).flatMap(foldPromise(_).toZIO)) } } @@ -1567,7 +1616,7 @@ object ZQuery { ev: A <:< Request[E, B], trace: Trace ): UIO[Result[R, E, B]] = { - val promise = Promise.unsafe.make[E, B](FiberId.None)(Unsafe.unsafe) + val promise = Promise.unsafe.make[E, B](FiberId.None)(Unsafe) Result.blockedExit( BlockedRequests.single(dataSource, BlockedRequest(request, promise)), Continue(promise) @@ -1615,7 +1664,7 @@ object ZQuery { )( f: A => ZQuery[R, E, B] )(implicit ev: CanFail[E], trace: Trace): ZQuery[R, Nothing, (Iterable[E], Iterable[B])] = - ZQuery.foreach(as)(f(_).either).map(partitionMap(_)(identity)) + ZQuery.foreach(as)(f(_).either).map(partitionMap(_)(ZIO.identityFn)) /** * Performs a query for each element in a collection, collecting the results @@ -1627,7 +1676,7 @@ object ZQuery { )( f: A => ZQuery[R, E, B] )(implicit ev: CanFail[E], trace: Trace): ZQuery[R, Nothing, (Iterable[E], Iterable[B])] = - ZQuery.foreachPar(as)(f(_).either).map(partitionMap(_)(identity)) + ZQuery.foreachPar(as)(f(_).either).map(partitionMap(_)(ZIO.identityFn)) /** * Accesses the whole environment of the query. @@ -1837,16 +1886,16 @@ object ZQuery { @deprecated("No longer used, kept for binary compatibility only", "0.7.4") val cachingEnabled: FiberRef[Boolean] = - FiberRef.unsafe.make(true)(Unsafe.unsafe) + FiberRef.unsafe.make(true)(Unsafe) val currentCache: FiberRef[Option[Cache]] = - FiberRef.unsafe.make(Option.empty[Cache])(Unsafe.unsafe) + FiberRef.unsafe.make(Option.empty[Cache])(Unsafe) private val disabledCache: FiberRef[Option[Cache]] = - FiberRef.unsafe.make(Option.empty[Cache])(Unsafe.unsafe) + FiberRef.unsafe.make(Option.empty[Cache])(Unsafe) val currentScope: FiberRef[QueryScope] = - FiberRef.unsafe.make[QueryScope](QueryScope.NoOp)(Unsafe.unsafe) + FiberRef.unsafe.make[QueryScope](QueryScope.NoOp)(Unsafe) final class Acquire[-R, +E, +A](private val acquire: () => ZIO[R, E, A]) extends AnyVal { def apply[R1](release: A => URIO[R1, Any]): Release[R with R1, E, A] = @@ -1882,28 +1931,23 @@ object ZQuery { .provideEnvironment(environment) .when(ref.getAndSet(false)) case Exit.Success(_) => - ZIO.unit + Exit.unit } } }.map { a => - ZQuery - .suspend(use(a)) - .foldCauseQuery( + use(a) + .foldCauseZIO( cause => - ZQuery.fromZIONow { - ZIO - .suspendSucceed(release(a, Exit.failCause(cause))) - .when(ref.getAndSet(false)) - .mapErrorCause(cause ++ _) *> - ZIO.refailCause(cause) - }, + ZIO + .suspendSucceed(release(a, Exit.failCause(cause))) + .when(ref.getAndSet(false)) + .mapErrorCause(cause ++ _) *> + ZIO.refailCause(cause), b => - ZQuery.fromZIONow { - ZIO - .suspendSucceed(release(a, Exit.succeed(b))) - .when(ref.getAndSet(false)) - .as(b) - } + ZIO + .suspendSucceed(release(a, Exit.succeed(b))) + .when(ref.getAndSet(false)) + .as(b) ) } } @@ -1914,6 +1958,9 @@ object ZQuery { @inline private def anyRefClassTag[A]: ClassTag[A] = ClassTag.AnyRef.asInstanceOf[ClassTag[A]] + private val FailCauseNone: Cause[Nothing] => ZQuery[Any, Nothing, Nothing] = + cause => ZQuery(Exit.failCause(cause)) + /** * `foreach` base implementation for sequential and batched modes */ @@ -1960,7 +2007,7 @@ object ZQuery { mode: Mode, mapOut: Array[B] => F[B] )(implicit trace: Trace): Result[R, E, F[B]] = { - implicit val classTag: ClassTag[B] = anyRefClassTag + implicit def ct: ClassTag[B] = anyRefClassTag @inline def addToArray(array: Array[B])(idxs: Array[Int], values: Array[B]): Unit = { var i = 0 diff --git a/zio-query/shared/src/main/scala/zio/query/internal/BlockedRequests.scala b/zio-query/shared/src/main/scala/zio/query/internal/BlockedRequests.scala index c1dac96..4d3e906 100644 --- a/zio-query/shared/src/main/scala/zio/query/internal/BlockedRequests.scala +++ b/zio-query/shared/src/main/scala/zio/query/internal/BlockedRequests.scala @@ -33,7 +33,7 @@ import scala.collection.mutable.ListBuffer * parallel, allowing for maximum possible batching and pipelining while * preserving ordering guarantees. */ -private[query] sealed trait BlockedRequests[-R] { self => +private[query] abstract class BlockedRequests[-R] { self => /** * Combines this collection of blocked requests with the specified collection @@ -54,10 +54,6 @@ private[query] sealed trait BlockedRequests[-R] { self => * specified functions. */ final def fold[Z](folder: Folder[R, Z]): Z = { - sealed trait BlockedRequestsCase - - case object BothCase extends BlockedRequestsCase - case object ThenCase extends BlockedRequestsCase @tailrec def loop(in: List[BlockedRequests[R]], out: List[Either[BlockedRequestsCase, Z]]): List[Z] = @@ -70,7 +66,7 @@ private[query] sealed trait BlockedRequests[-R] { self => loop(left :: right :: blockedRequests, Left(ThenCase) :: out) case Empty :: blockedRequests => loop(blockedRequests, Right(folder.emptyCase) :: out) - case Nil => + case _ /* Nil */ => out.foldLeft[List[Z]](List.empty) { case (acc, Right(blockedRequests)) => blockedRequests :: acc @@ -105,8 +101,10 @@ private[query] sealed trait BlockedRequests[-R] { self => /** * Executes all requests, submitting requests to each data source in parallel. */ - def run(implicit trace: Trace): ZIO[R, Nothing, Unit] = { - val flattened = BlockedRequests.flatten(self) + final def run(implicit trace: Trace): ZIO[R, Nothing, Unit] = { + if (self eq Empty) return Exit.unit + + val flattened = self.flatten ZIO.foreachDiscard(flattened) { requestsByDataSource => ZIO.foreachParDiscard(requestsByDataSource.toIterable) { case (dataSource, sequential) => val requests = sequential.map(_.map(_.request)) @@ -140,6 +138,32 @@ private[query] sealed trait BlockedRequests[-R] { self => } } } + + /** + * Flattens a collection of blocked requests into a collection of pipelined + * and batched requests that can be submitted for execution. + */ + private def flatten: List[Sequential[R]] = { + @tailrec + def loop( + blockedRequests: List[BlockedRequests[R]], + flattened: List[Sequential[R]], + sequential: ListBuffer[BlockedRequests[R]], + parallel: Parallel[R] + ): List[Sequential[R]] = { + blockedRequests.foreach(step(parallel, sequential)) + val updated = merge(flattened, parallel) + if (sequential.isEmpty) updated.reverse + else { + val reqs = sequential.result() + sequential.clear() + parallel.clear() + loop(reqs, updated, sequential, parallel) + } + } + + loop(List(self), List.empty, ListBuffer.empty[BlockedRequests[R]], Parallel.empty[R]) + } } private[query] object BlockedRequests { @@ -159,9 +183,7 @@ private[query] object BlockedRequests { final case class Both[-R](left: BlockedRequests[R], right: BlockedRequests[R]) extends BlockedRequests[R] - case object Empty extends BlockedRequests[Any] { - override def run(implicit trace: Trace): ZIO[Any, Nothing, Unit] = Exit.unit - } + case object Empty extends BlockedRequests[Any] final case class Single[-R, A](dataSource: DataSource[R, A], blockedRequest: BlockedRequest[A]) extends BlockedRequests[R] @@ -201,29 +223,9 @@ private[query] object BlockedRequests { } } - /** - * Flattens a collection of blocked requests into a collection of pipelined - * and batched requests that can be submitted for execution. - */ - private def flatten[R]( - blockedRequests: BlockedRequests[R] - ): List[Sequential[R]] = { - - @tailrec - def loop( - blockedRequests: List[BlockedRequests[R]], - flattened: List[Sequential[R]] - ): List[Sequential[R]] = { - val parallel = Parallel.empty - val sequential = ListBuffer.empty[BlockedRequests[R]] - blockedRequests.foreach(step(parallel, sequential)) - val updated = merge(flattened, parallel) - if (sequential.isEmpty) updated.reverse - else loop(sequential.result(), updated) - } - - loop(List(blockedRequests), List.empty) - } + private sealed trait BlockedRequestsCase + private case object BothCase extends BlockedRequestsCase + private case object ThenCase extends BlockedRequestsCase /** * Takes one step in evaluating a collection of blocked requests, returning a diff --git a/zio-query/shared/src/main/scala/zio/query/internal/Continue.scala b/zio-query/shared/src/main/scala/zio/query/internal/Continue.scala index 625d809..6f97cbe 100644 --- a/zio-query/shared/src/main/scala/zio/query/internal/Continue.scala +++ b/zio-query/shared/src/main/scala/zio/query/internal/Continue.scala @@ -18,7 +18,6 @@ package zio.query.internal import zio._ import zio.query._ -import zio.query.internal.Continue._ import zio.stacktracer.TracingImplicits.disableAutoTrace /** @@ -30,166 +29,122 @@ import zio.stacktracer.TracingImplicits.disableAutoTrace * internally to determine whether it is safe to pipeline two requests that must * be executed sequentially. */ -private[query] sealed trait Continue[-R, +E, +A] { self => +private[query] abstract class Continue[-R, +E, +A] { self => + + /** + * Recovers from all errors. + */ + def catchAll[R1 <: R, E1, A1 >: A]( + failure: E => ZQuery[R1, E1, A1] + )(implicit trace: Trace): Continue[R1, E1, A1] + + /** + * Recovers from all errors with the provided Cause. + */ + def catchAllCause[R1 <: R, E1, A1 >: A]( + failure: Cause[E] => ZQuery[R1, E1, A1] + )(implicit trace: Trace): Continue[R1, E1, A1] /** * Purely folds over the failure and success types of this continuation. */ - final def fold[B](failure: E => B, success: A => B)(implicit + def fold[B](failure: E => B, success: A => B)(implicit ev: CanFail[E], trace: Trace - ): Continue[R, Nothing, B] = - self match { - case Effect(query) => Effect(query.fold(failure, success)) - case Get(io) => Get(io.foldZIO(e => Exit.succeed(failure(e)), a => Exit.succeed(success(a)))) - } + ): Continue[R, Nothing, B] /** * Effectually folds over the failure and success types of this continuation. */ - final def foldCauseQuery[R1 <: R, E1, B]( + def foldCauseQuery[R1 <: R, E1, B]( failure: Cause[E] => ZQuery[R1, E1, B], success: A => ZQuery[R1, E1, B] - )(implicit trace: Trace): Continue[R1, E1, B] = - self match { - case Effect(query) => Effect(query.foldCauseQuery(failure, success)) - case Get(io) => Effect(ZQuery.fromZIONow(io).foldCauseQuery(failure, success)) - } + )(implicit trace: Trace): Continue[R1, E1, B] - final def foldCauseZIO[R1 <: R, E1, B]( + def foldCauseZIO[R1 <: R, E1, B]( failure: Cause[E] => ZIO[R1, E1, B], success: A => ZIO[R1, E1, B] - )(implicit trace: Trace): Continue[R1, E1, B] = - self match { - case Effect(query) => Effect(query.foldCauseZIO(failure, success)) - case Get(io) => Get(io.foldCauseZIO(failure, success)) - } + )(implicit trace: Trace): Continue[R1, E1, B] - final def foldZIO[R1 <: R, E1, B]( + def foldQuery[R1 <: R, E1, B]( + failure: E => ZQuery[R1, E1, B], + success: A => ZQuery[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] + + def foldZIO[R1 <: R, E1, B]( failure: E => ZIO[R1, E1, B], success: A => ZIO[R1, E1, B] - )(implicit trace: Trace): Continue[R1, E1, B] = - foldCauseZIO(_.failureOrCause.fold(failure, Exit.failCause), success) + )(implicit trace: Trace): Continue[R1, E1, B] /** * Purely maps over the success type of this continuation. */ - final def map[B](f: A => B)(implicit trace: Trace): Continue[R, E, B] = - self match { - case Effect(query) => Effect(query.map(f)) - case Get(io) => Get(io.map(f)) - } + def map[B](f: A => B)(implicit trace: Trace): Continue[R, E, B] - final def mapBothCause[E1, B](failure: Cause[E] => Cause[E1], success: A => B)(implicit + def mapBothCause[E1, B](failure: Cause[E] => Cause[E1], success: A => B)(implicit ev: CanFail[E], trace: Trace - ): Continue[R, E1, B] = - self match { - case Effect(query) => Effect(query.mapBothCause(failure, success)) - case Get(io) => Get(io.foldCauseZIO(e => Exit.failCause(failure(e)), a => Exit.succeed(success(a)))) - } + ): Continue[R, E1, B] /** * Transforms all data sources with the specified data source aspect. */ - final def mapDataSources[R1 <: R](f: DataSourceAspect[R1])(implicit trace: Trace): Continue[R1, E, A] = - self match { - case Effect(query) => Effect(query.mapDataSources(f)) - case Get(io) => Get(io) - } + def mapDataSources[R1 <: R](f: DataSourceAspect[R1])(implicit trace: Trace): Continue[R1, E, A] /** * Purely maps over the failure type of this continuation. */ - final def mapError[E1](f: E => E1)(implicit ev: CanFail[E], trace: Trace): Continue[R, E1, A] = - self match { - case Effect(query) => Effect(query.mapError(f)) - case Get(io) => Get(io.mapError(f)) - } + def mapError[E1](f: E => E1)(implicit ev: CanFail[E], trace: Trace): Continue[R, E1, A] /** * Purely maps over the failure cause of this continuation. */ - final def mapErrorCause[E1](f: Cause[E] => Cause[E1])(implicit trace: Trace): Continue[R, E1, A] = - self match { - case Effect(query) => Effect(query.mapErrorCause(f)) - case Get(io) => Get(io.mapErrorCause(f)) - } + def mapErrorCause[E1](f: Cause[E] => Cause[E1])(implicit trace: Trace): Continue[R, E1, A] /** * Effectually maps over the success type of this continuation. */ - final def mapQuery[R1 <: R, E1 >: E, B]( + def mapQuery[R1 <: R, E1 >: E, B]( f: A => ZQuery[R1, E1, B] - )(implicit trace: Trace): Continue[R1, E1, B] = - self match { - case Effect(query) => Effect(query.flatMap(f)) - case Get(io) => Effect(ZQuery.fromZIONow(io).flatMap(f)) - } + )(implicit trace: Trace): Continue[R1, E1, B] /** * Effectually maps over the success type of this continuation. */ - final def mapZIO[R1 <: R, E1 >: E, B]( + def mapZIO[R1 <: R, E1 >: E, B]( f: A => ZIO[R1, E1, B] - )(implicit trace: Trace): Continue[R1, E1, B] = - self match { - case Effect(query) => Effect(query.mapZIO(f)) - case Get(io) => Get(io.flatMap(f)) - } + )(implicit trace: Trace): Continue[R1, E1, B] /** * Purely contramaps over the environment type of this continuation. */ - final def provideSomeEnvironment[R0]( + def provideSomeEnvironment[R0]( f: Described[ZEnvironment[R0] => ZEnvironment[R]] - )(implicit trace: Trace): Continue[R0, E, A] = - self match { - case Effect(query) => Effect(query.provideSomeEnvironment(f)) - case Get(io) => Get(io.provideSomeEnvironment(f.value)) - } + )(implicit trace: Trace): Continue[R0, E, A] /** * Combines this continuation with that continuation using the specified * function, in sequence. */ - final def zipWith[R1 <: R, E1 >: E, B, C]( + def zipWith[R1 <: R, E1 >: E, B, C]( that: Continue[R1, E1, B] - )(f: (A, B) => C)(implicit trace: Trace): Continue[R1, E1, C] = - (self, that) match { - case (Effect(l), Effect(r)) => Effect(l.zipWith(r)(f)) - case (Effect(l), Get(r)) => Effect(l.zipWith(ZQuery.fromZIONow(r))(f)) - case (Get(l), Effect(r)) => Effect(ZQuery.fromZIONow(l).zipWith(r)(f)) - case (Get(l), Get(r)) => Get(l.zipWith(r)(f)) - } + )(f: (A, B) => C)(implicit trace: Trace): Continue[R1, E1, C] /** * Combines this continuation with that continuation using the specified * function, in parallel. */ - final def zipWithPar[R1 <: R, E1 >: E, B, C]( + def zipWithPar[R1 <: R, E1 >: E, B, C]( that: Continue[R1, E1, B] - )(f: (A, B) => C)(implicit trace: Trace): Continue[R1, E1, C] = - (self, that) match { - case (Effect(l), Effect(r)) => Effect(l.zipWithPar(r)(f)) - case (Effect(l), Get(r)) => Effect(l.zipWith(ZQuery.fromZIONow(r))(f)) - case (Get(l), Effect(r)) => Effect(ZQuery.fromZIONow(l).zipWith(r)(f)) - case (Get(l), Get(r)) => Get(l.zipWith(r)(f)) - } + )(f: (A, B) => C)(implicit trace: Trace): Continue[R1, E1, C] /** * Combines this continuation with that continuation using the specified * function, batching requests to data sources. */ - final def zipWithBatched[R1 <: R, E1 >: E, B, C]( + def zipWithBatched[R1 <: R, E1 >: E, B, C]( that: Continue[R1, E1, B] - )(f: (A, B) => C)(implicit trace: Trace): Continue[R1, E1, C] = - (self, that) match { - case (Effect(l), Effect(r)) => Effect(l.zipWithBatched(r)(f)) - case (Effect(l), Get(r)) => Effect(l.zipWith(ZQuery.fromZIONow(r))(f)) - case (Get(l), Effect(r)) => Effect(ZQuery.fromZIONow(l).zipWith(r)(f)) - case (Get(l), Get(r)) => Get(l.zipWith(r)(f)) - } + )(f: (A, B) => C)(implicit trace: Trace): Continue[R1, E1, C] } private[query] object Continue { @@ -214,6 +169,201 @@ private[query] object Continue { def get[R, E, A](io: ZIO[R, E, A]): Continue[R, E, A] = Get(io) - final case class Effect[R, E, A](query: ZQuery[R, E, A]) extends Continue[R, E, A] - final case class Get[R, E, A](io: ZIO[R, E, A]) extends Continue[R, E, A] + final case class Effect[R, E, A](query: ZQuery[R, E, A]) extends Continue[R, E, A] { + override def catchAll[R1 <: R, E1, A1 >: A]( + failure: E => ZQuery[R1, E1, A1] + )(implicit trace: Trace): Continue[R1, E1, A1] = + Effect(query.catchAll(failure)) + + override def catchAllCause[R1 <: R, E1, A1 >: A]( + failure: Cause[E] => ZQuery[R1, E1, A1] + )(implicit trace: Trace): Continue[R1, E1, A1] = + Effect(query.catchAllCause(failure)) + + override def fold[B](failure: E => B, success: A => B)(implicit + ev: CanFail[E], + trace: Trace + ): Continue[R, Nothing, B] = + Effect(query.fold(failure, success)) + + override def foldCauseQuery[R1 <: R, E1, B]( + failure: Cause[E] => ZQuery[R1, E1, B], + success: A => ZQuery[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] = + Effect(query.foldCauseQuery(failure, success)) + + override def foldCauseZIO[R1 <: R, E1, B]( + failure: Cause[E] => ZIO[R1, E1, B], + success: A => ZIO[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] = + Effect(query.foldCauseZIO(failure, success)) + + override def foldQuery[R1 <: R, E1, B]( + failure: E => ZQuery[R1, E1, B], + success: A => ZQuery[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] = + Effect(query.foldQuery(failure, success)) + + override def foldZIO[R1 <: R, E1, B]( + failure: E => ZIO[R1, E1, B], + success: A => ZIO[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] = + Effect(query.foldZIO(failure, success)) + + override def map[B](f: A => B)(implicit trace: Trace): Continue[R, E, B] = + Effect(query.map(f)) + + override def mapBothCause[E1, B](failure: Cause[E] => Cause[E1], success: A => B)(implicit + ev: CanFail[E], + trace: Trace + ): Continue[R, E1, B] = + Effect(query.mapBothCause(failure, success)) + + override def mapDataSources[R1 <: R](f: DataSourceAspect[R1])(implicit trace: Trace): Continue[R1, E, A] = + Effect(query.mapDataSources(f)) + + override def mapError[E1](f: E => E1)(implicit ev: CanFail[E], trace: Trace): Continue[R, E1, A] = + Effect(query.mapError(f)) + + override def mapErrorCause[E1](f: Cause[E] => Cause[E1])(implicit trace: Trace): Continue[R, E1, A] = + Effect(query.mapErrorCause(f)) + + override def mapQuery[R1 <: R, E1 >: E, B]( + f: A => ZQuery[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] = + Effect(query.flatMap(f)) + + override def mapZIO[R1 <: R, E1 >: E, B]( + f: A => ZIO[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] = + Effect(query.mapZIO(f)) + + override def provideSomeEnvironment[R0]( + f: Described[ZEnvironment[R0] => ZEnvironment[R]] + )(implicit trace: Trace): Continue[R0, E, A] = + Effect(query.provideSomeEnvironment(f)) + + override def zipWith[R1 <: R, E1 >: E, B, C]( + that: Continue[R1, E1, B] + )(f: (A, B) => C)(implicit trace: Trace): Continue[R1, E1, C] = + that match { + case Effect(r) => Effect(query.zipWith(r)(f)) + case Get(r) => Effect(query.zipWith(ZQuery.fromZIONow(r))(f)) + } + + override def zipWithPar[R1 <: R, E1 >: E, B, C]( + that: Continue[R1, E1, B] + )(f: (A, B) => C)(implicit trace: Trace): Continue[R1, E1, C] = + that match { + case Effect(r) => Effect(query.zipWithPar(r)(f)) + case Get(r) => Effect(query.zipWith(ZQuery.fromZIONow(r))(f)) + } + + override def zipWithBatched[R1 <: R, E1 >: E, B, C]( + that: Continue[R1, E1, B] + )(f: (A, B) => C)(implicit trace: Trace): Continue[R1, E1, C] = + that match { + case Effect(r) => Effect(query.zipWithBatched(r)(f)) + case Get(r) => Effect(query.zipWith(ZQuery.fromZIONow(r))(f)) + } + } + + final case class Get[R, E, A](io: ZIO[R, E, A]) extends Continue[R, E, A] { + override def catchAll[R1 <: R, E1, A1 >: A]( + failure: E => ZQuery[R1, E1, A1] + )(implicit trace: Trace): Continue[R1, E1, A1] = + Effect(ZQuery.fromZIONow(io).catchAll(failure)) + + override def catchAllCause[R1 <: R, E1, A1 >: A]( + failure: Cause[E] => ZQuery[R1, E1, A1] + )(implicit trace: Trace): Continue[R1, E1, A1] = + Effect(ZQuery.fromZIONow(io).catchAllCause(failure)) + + override def fold[B](failure: E => B, success: A => B)(implicit + ev: CanFail[E], + trace: Trace + ): Continue[R, Nothing, B] = + Get(io.fold(failure, success)) + + override def foldCauseQuery[R1 <: R, E1, B]( + failure: Cause[E] => ZQuery[R1, E1, B], + success: A => ZQuery[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] = + Effect(ZQuery.fromZIONow(io).foldCauseQuery(failure, success)) + + override def foldCauseZIO[R1 <: R, E1, B]( + failure: Cause[E] => ZIO[R1, E1, B], + success: A => ZIO[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] = + Get(io.foldCauseZIO(failure, success)) + + override def foldQuery[R1 <: R, E1, B]( + failure: E => ZQuery[R1, E1, B], + success: A => ZQuery[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] = + Effect(ZQuery.fromZIONow(io).foldQuery(failure, success)) + + override def foldZIO[R1 <: R, E1, B]( + failure: E => ZIO[R1, E1, B], + success: A => ZIO[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] = + Get(io.foldZIO(failure, success)) + + override def map[B](f: A => B)(implicit trace: Trace): Continue[R, E, B] = + Get(io.map(f)) + + override def mapBothCause[E1, B](failure: Cause[E] => Cause[E1], success: A => B)(implicit + ev: CanFail[E], + trace: Trace + ): Continue[R, E1, B] = + Get(io.foldCauseZIO(e => Exit.failCause(failure(e)), a => Exit.succeed(success(a)))) + + override def mapDataSources[R1 <: R](f: DataSourceAspect[R1])(implicit trace: Trace): Continue[R1, E, A] = + this + + override def mapError[E1](f: E => E1)(implicit ev: CanFail[E], trace: Trace): Continue[R, E1, A] = + Get(io.mapError(f)) + + override def mapErrorCause[E1](f: Cause[E] => Cause[E1])(implicit trace: Trace): Continue[R, E1, A] = + Get(io.mapErrorCause(f)) + + override def mapQuery[R1 <: R, E1 >: E, B]( + f: A => ZQuery[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] = + Effect(ZQuery.fromZIONow(io).flatMap(f)) + + override def mapZIO[R1 <: R, E1 >: E, B]( + f: A => ZIO[R1, E1, B] + )(implicit trace: Trace): Continue[R1, E1, B] = + Get(io.flatMap(f)) + + override def provideSomeEnvironment[R0]( + f: Described[ZEnvironment[R0] => ZEnvironment[R]] + )(implicit trace: Trace): Continue[R0, E, A] = + Get(io.provideSomeEnvironment(f.value)) + + override def zipWith[R1 <: R, E1 >: E, B, C]( + that: Continue[R1, E1, B] + )(f: (A, B) => C)(implicit trace: Trace): Continue[R1, E1, C] = + that match { + case Effect(r) => Effect(ZQuery.fromZIONow(io).zipWith(r)(f)) + case Get(r) => Get(io.zipWith(r)(f)) + } + + override def zipWithPar[R1 <: R, E1 >: E, B, C]( + that: Continue[R1, E1, B] + )(f: (A, B) => C)(implicit trace: Trace): Continue[R1, E1, C] = + that match { + case Effect(r) => Effect(ZQuery.fromZIONow(io).zipWith(r)(f)) + case Get(r) => Get(io.zipWith(r)(f)) + } + + override def zipWithBatched[R1 <: R, E1 >: E, B, C]( + that: Continue[R1, E1, B] + )(f: (A, B) => C)(implicit trace: Trace): Continue[R1, E1, C] = + that match { + case Effect(r) => Effect(ZQuery.fromZIONow(io).zipWith(r)(f)) + case Get(r) => Get(io.zipWith(r)(f)) + } + } } diff --git a/zio-query/shared/src/main/scala/zio/query/internal/Parallel.scala b/zio-query/shared/src/main/scala/zio/query/internal/Parallel.scala index eac8c86..d88ec81 100644 --- a/zio-query/shared/src/main/scala/zio/query/internal/Parallel.scala +++ b/zio-query/shared/src/main/scala/zio/query/internal/Parallel.scala @@ -59,6 +59,8 @@ private[query] final class Parallel[-R]( } new Sequential(builder.result()) } + + def clear(): Unit = map.clear() } private[query] object Parallel { diff --git a/zio-query/shared/src/main/scala/zio/query/internal/Result.scala b/zio-query/shared/src/main/scala/zio/query/internal/Result.scala index 4d00a8a..bb6055f 100644 --- a/zio-query/shared/src/main/scala/zio/query/internal/Result.scala +++ b/zio-query/shared/src/main/scala/zio/query/internal/Result.scala @@ -26,20 +26,7 @@ import zio.stacktracer.TracingImplicits.disableAutoTrace * may either by done with a value `A`, blocked on a set of requests to data * sources that require an environment `R`, or failed with an `E`. */ -private[query] sealed trait Result[-R, +E, +A] { self => - - /** - * Folds over the successful or failed result. - */ - final def fold[B](failure: E => B, success: A => B)(implicit - ev: CanFail[E], - trace: Trace - ): Result[R, Nothing, B] = - self match { - case Blocked(br, c) => blocked(br, c.fold(failure, success)) - case Done(a) => done(success(a)) - case Fail(e) => e.failureOrCause.fold(e => done(failure(e)), c => fail(c)) - } +private[query] sealed abstract class Result[-R, +E, +A] { self => /** * Maps the specified function over the successful value of this result. @@ -48,47 +35,28 @@ private[query] sealed trait Result[-R, +E, +A] { self => self match { case Blocked(br, c) => blocked(br, c.map(f)) case Done(a) => done(f(a)) - case Fail(e) => fail(e) + case e => e.widen } /** * Transforms all data sources with the specified data source aspect. */ - def mapDataSources[R1 <: R](f: DataSourceAspect[R1])(implicit trace: Trace): Result[R1, E, A] = + final def mapDataSources[R1 <: R](f: DataSourceAspect[R1])(implicit trace: Trace): Result[R1, E, A] = self match { case Blocked(br, c) => Result.blocked(br.mapDataSources(f), c.mapDataSources(f)) - case Done(a) => Result.done(a) - case Fail(e) => Result.fail(e) - } - - /** - * Maps the specified function over the failed value of this result. - */ - final def mapError[E1](f: E => E1)(implicit ev: CanFail[E], trace: Trace): Result[R, E1, A] = - self match { - case Blocked(br, c) => blocked(br, c.mapError(f)) - case Done(a) => done(a) - case Fail(e) => fail(e.map(f)) + case doneOrFail => doneOrFail.widen } /** * Maps the specified function over the failure cause of this result. */ - def mapErrorCause[E1](f: Cause[E] => Cause[E1])(implicit trace: Trace): Result[R, E1, A] = + final def mapErrorCause[E1](f: Cause[E] => Cause[E1])(implicit trace: Trace): Result[R, E1, A] = self match { case Blocked(br, c) => blocked(br, c.mapErrorCause(f)) - case Done(a) => done(a) - case Fail(e) => fail(f(e)) + case Fail(e) => Fail(f(e)) + case done => done.widen } - /** - * Provides this result with its required environment. - */ - final def provideEnvironment( - r: Described[ZEnvironment[R]] - )(implicit trace: Trace): Result[Any, E, A] = - provideSomeEnvironment(Described(_ => r.value, s"_ => ${r.description}")) - /** * Provides this result with part of its required environment. */ @@ -97,9 +65,12 @@ private[query] sealed trait Result[-R, +E, +A] { self => )(implicit trace: Trace): Result[R0, E, A] = self match { case Blocked(br, c) => blocked(br.provideSomeEnvironment(f), c.provideSomeEnvironment(f)) - case Done(a) => done(a) - case Fail(e) => fail(e) + case doneOrFail => doneOrFail.widen } + + @inline + final def widen[R1, E1, A1]: Result[R1, E1, A1] = + self.asInstanceOf[Result[R1, E1, A1]] } private[query] object Result { @@ -133,7 +104,8 @@ private[query] object Result { Fail(cause) def failExit[E](cause: Cause[E]): Exit[Nothing, Result[Any, E, Nothing]] = - Exit.Success(Fail(cause)) + if (cause.isFailure) Exit.Success(Fail(cause)) + else Exit.Failure(cause.asInstanceOf[Cause[Nothing]]) /** * Lifts an `Exit` into a result.