Skip to content

Commit

Permalink
refactor: fix naming for Http operators
Browse files Browse the repository at this point in the history
  • Loading branch information
tusharmath committed Jan 15, 2022
1 parent 10df2c6 commit 00feb56
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class HttpRouteTextPerf {
private val res = Response.text("HELLO WORLD")
private val app = Http.succeed(res)
private val req: Request = Request(Method.GET, URL(!!))
private val httpProgram = ZIO.foreach_(0 to 1000) { _ => app.execute(req).toEffect }
private val httpProgram = ZIO.foreach_(0 to 1000) { _ => app.execute(req).toZIO }
private val UIOProgram = ZIO.foreach_(0 to 1000) { _ => UIO(res) }

@Benchmark
Expand Down
2 changes: 1 addition & 1 deletion zio-http-test/src/main/scala/zhttp/test/test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import zio.ZIO

package object test {
implicit class HttpWithTest[R, E, A, B](http: Http[R, E, A, B]) {
def apply(req: A): ZIO[R, Option[E], B] = http.execute(req).toEffect
def apply(req: A): ZIO[R, Option[E], B] = http.execute(req).toZIO
}
}
2 changes: 1 addition & 1 deletion zio-http/src/main/scala/zhttp/endpoint/CanConstruct.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ object CanConstruct {
Http
.collectHttp[Request] { case req =>
route.extract(req) match {
case Some(value) => Http.fromEffect(f(Request.ParameterizedRequest(req, value)))
case Some(value) => Http.fromZIO(f(Request.ParameterizedRequest(req, value)))
case None => Http.empty
}
}
Expand Down
12 changes: 6 additions & 6 deletions zio-http/src/main/scala/zhttp/http/HExit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ private[zhttp] sealed trait HExit[-R, +E, +A] { self =>
Effect(
zio.foldM(
{
case Some(error) => ee(error).toEffect
case None => dd.toEffect
case Some(error) => ee(error).toZIO
case None => dd.toZIO
},
a => aa(a).toEffect,
a => aa(a).toZIO,
),
)
case HExit.Empty => dd
Expand All @@ -59,7 +59,7 @@ private[zhttp] sealed trait HExit[-R, +E, +A] { self =>
def orElse[R1 <: R, E1, A1 >: A](other: HExit[R1, E1, A1]): HExit[R1, E1, A1] =
self.foldExit(_ => other, HExit.succeed, HExit.empty)

def toEffect: ZIO[R, Option[E], A] = self match {
def toZIO: ZIO[R, Option[E], A] = self match {
case HExit.Success(a) => ZIO.succeed(a)
case HExit.Failure(e) => ZIO.fail(Option(e))
case HExit.Empty => ZIO.fail(None)
Expand All @@ -68,12 +68,12 @@ private[zhttp] sealed trait HExit[-R, +E, +A] { self =>
}

object HExit {
def effect[R, E, A](z: ZIO[R, E, A]): HExit[R, E, A] = Effect(z.mapError(Option(_)))

def empty: HExit[Any, Nothing, Nothing] = Empty

def fail[E](e: E): HExit[Any, E, Nothing] = Failure(e)

def fromZIO[R, E, A](z: ZIO[R, E, A]): HExit[R, E, A] = Effect(z.mapError(Option(_)))

def succeed[A](a: A): HExit[Any, Nothing, A] = Success(a)

def unit: HExit[Any, Nothing, Unit] = HExit.succeed(())
Expand Down
99 changes: 45 additions & 54 deletions zio-http/src/main/scala/zhttp/http/Http.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ sealed trait Http[-R, +E, -A, +B] extends (A => ZIO[R, Option[E], B]) { self =>
/**
* Consumes the input and executes the Http.
*/
final def apply(a: A): ZIO[R, Option[E], B] = execute(a).toEffect
final def apply(a: A): ZIO[R, Option[E], B] = execute(a).toZIO

/**
* Makes the app resolve with a constant value
Expand Down Expand Up @@ -103,7 +103,7 @@ sealed trait Http[-R, +E, -A, +B] extends (A => ZIO[R, Option[E], B]) { self =>
/**
* Transforms the input of the http before passing it on to the current Http
*/
final def contraFlatMap[X]: MkContraFlatMap[R, E, A, B, X] = MkContraFlatMap[R, E, A, B, X](self)
final def contraFlatMap[X]: PartialContraFlatMap[R, E, A, B, X] = PartialContraFlatMap[R, E, A, B, X](self)

/**
* Transforms the input of the http before passing it on to the current Http
Expand All @@ -114,7 +114,7 @@ sealed trait Http[-R, +E, -A, +B] extends (A => ZIO[R, Option[E], B]) { self =>
* Transforms the input of the http before giving it effectfully
*/
final def contramapZIO[R1 <: R, E1 >: E, X](xa: X => ZIO[R1, E1, A]): Http[R1, E1, X, B] =
Http.fromEffectFunction[X](xa) >>> self
Http.fromFunctionZIO[X](xa) >>> self

/**
* Named alias for `++`
Expand Down Expand Up @@ -178,7 +178,7 @@ sealed trait Http[-R, +E, -A, +B] extends (A => ZIO[R, Option[E], B]) { self =>
* Transforms the output of the http effectfully
*/
final def mapZIO[R1 <: R, E1 >: E, C](bFc: B => ZIO[R1, E1, C]): Http[R1, E1, A, C] =
self >>> Http.fromEffectFunction(bFc)
self >>> Http.fromFunctionZIO(bFc)

/**
* Named alias for `<>`
Expand Down Expand Up @@ -263,9 +263,9 @@ sealed trait Http[-R, +E, -A, +B] extends (A => ZIO[R, Option[E], B]) { self =>
h: ZIO[R1, E1, Any],
): Http[R1, E1, A, B] =
tapAll(
e => Http.fromEffect(f(e)),
x => Http.fromEffect(g(x)),
Http.fromEffect(h),
e => Http.fromZIO(f(e)),
x => Http.fromZIO(g(x)),
Http.fromZIO(h),
)

/**
Expand All @@ -282,19 +282,19 @@ sealed trait Http[-R, +E, -A, +B] extends (A => ZIO[R, Option[E], B]) { self =>
* Returns an Http that effectfully peeks at the failure of this Http.
*/
final def tapErrorZIO[R1 <: R, E1 >: E](f: E => ZIO[R1, E1, Any]): Http[R1, E1, A, B] =
self.tapError(e => Http.fromEffect(f(e)))
self.tapError(e => Http.fromZIO(f(e)))

/**
* Returns an Http that effectfully peeks at the success of this Http.
*/
final def tapZIO[R1 <: R, E1 >: E](f: B => ZIO[R1, E1, Any]): Http[R1, E1, A, B] =
self.tap(v => Http.fromEffect(f(v)))
self.tap(v => Http.fromZIO(f(v)))

/**
* Unwraps an Http that returns a ZIO of Http
*/
final def unwrap[R1 <: R, E1 >: E, C](implicit ev: B <:< ZIO[R1, E1, C]): Http[R1, E1, A, C] =
self.flatMap(Http.fromEffect(_))
self.flatMap(Http.fromZIO(_))

/**
* Widens the type of the output
Expand All @@ -317,14 +317,14 @@ sealed trait Http[-R, +E, -A, +B] extends (A => ZIO[R, Option[E], B]) { self =>
*/
final private[zhttp] def execute(a: A): HExit[R, E, B] =
self match {
case Http.Empty => HExit.empty
case Http.Identity => HExit.succeed(a.asInstanceOf[B])
case Succeed(b) => HExit.succeed(b)
case Fail(e) => HExit.fail(e)
case FromEffectFunction(f) => HExit.effect(f(a))
case Collect(pf) => if (pf.isDefinedAt(a)) HExit.succeed(pf(a)) else HExit.empty
case Chain(self, other) => self.execute(a).flatMap(b => other.execute(b))
case Race(self, other) =>
case Http.Empty => HExit.empty
case Http.Identity => HExit.succeed(a.asInstanceOf[B])
case Succeed(b) => HExit.succeed(b)
case Fail(e) => HExit.fail(e)
case FromFunctionZIO(f) => HExit.fromZIO(f(a))
case Collect(pf) => if (pf.isDefinedAt(a)) HExit.succeed(pf(a)) else HExit.empty
case Chain(self, other) => self.execute(a).flatMap(b => other.execute(b))
case Race(self, other) =>
(self.execute(a), other.execute(a)) match {
case (HExit.Effect(self), HExit.Effect(other)) =>
Http.fromOptionFunction[Any](_ => self.raceFirst(other)).execute(a)
Expand Down Expand Up @@ -406,14 +406,14 @@ object Http {
/**
* Creates an HTTP app which accepts a request and produces response.
*/
def collect[A]: Http.MakeCollect[A] = Http.MakeCollect(())
def collect[A]: Http.PartialCollect[A] = Http.PartialCollect(())

def collectHttp[A]: Http.MakeCollectHttp[A] = Http.MakeCollectHttp(())
def collectHttp[A]: Http.PartialCollectHttp[A] = Http.PartialCollectHttp(())

/**
* Creates an HTTP app which accepts a request and produces response effectfully.
*/
def collectZIO[A]: Http.MakeCollectZIO[A] = Http.MakeCollectZIO(())
def collectZIO[A]: Http.PartialCollectZIO[A] = Http.PartialCollectZIO(())

/**
* Combines multiple Http apps into one
Expand Down Expand Up @@ -451,7 +451,7 @@ object Http {
* Flattens an Http app of an that returns an effectful response
*/
def flattenZIO[R, E, A, B](http: Http[R, E, A, ZIO[R, E, B]]): Http[R, E, A, B] =
http.flatMap(Http.fromEffect)
http.flatMap(Http.fromZIO)

/**
* Creates an Http app that responds with 403 - Forbidden status code
Expand All @@ -463,16 +463,6 @@ object Http {
*/
def fromData(data: HttpData): HttpApp[Any, Nothing] = response(Response(data = data))

/**
* Converts a ZIO to an Http type
*/
def fromEffect[R, E, B](effect: ZIO[R, E, B]): Http[R, E, Any, B] = Http.fromEffectFunction(_ => effect)

/**
* Creates an Http app from a function that returns a ZIO
*/
def fromEffectFunction[A]: Http.MakeFromEffectFunction[A] = Http.MakeFromEffectFunction(())

/*
* Creates an Http app from the contents of a file
*/
Expand All @@ -481,30 +471,35 @@ object Http {
/**
* Creates a Http from a pure function
*/
def fromFunction[A]: FromFunction[A] = new FromFunction[A](())
def fromFunction[A]: PartialFromFunction[A] = new PartialFromFunction[A](())

/**
* Creates a Http from an effectful pure function
*/
def fromFunctionZIO[A]: FromFunctionZIO[A] = new FromFunctionZIO[A](())
def fromFunctionZIO[A]: PartialFromFunctionZIO[A] = new PartialFromFunctionZIO[A](())

/**
* Creates an `Http` from a function that takes a value of type `A` and returns with a `ZIO[R, Option[E], B]`. The
* returned effect can fail with a `None` to signal "not found" to the backend.
*/
def fromOptionFunction[A]: FromOptionFunction[A] = new FromOptionFunction(())
def fromOptionFunction[A]: PartialFromOptionFunction[A] = new PartialFromOptionFunction(())

/**
* Creates a Http that always succeeds with a 200 status code and the provided ZStream as the body
*/
def fromStream[R](stream: ZStream[R, Throwable, String], charset: Charset = HTTP_CHARSET): HttpApp[R, Nothing] =
Http.fromEffect(ZIO.environment[R].map(r => Http.fromData(HttpData.fromStream(stream.provide(r), charset)))).flatten
Http.fromZIO(ZIO.environment[R].map(r => Http.fromData(HttpData.fromStream(stream.provide(r), charset)))).flatten

/**
* Creates a Http that always succeeds with a 200 status code and the provided ZStream as the body
*/
def fromStream[R](stream: ZStream[R, Throwable, Byte]): HttpApp[R, Nothing] =
Http.fromEffect(ZIO.environment[R].map(r => Http.fromData(HttpData.fromStream(stream.provide(r))))).flatten
Http.fromZIO(ZIO.environment[R].map(r => Http.fromData(HttpData.fromStream(stream.provide(r))))).flatten

/**
* Converts a ZIO to an Http type
*/
def fromZIO[R, E, B](effect: ZIO[R, E, B]): Http[R, E, Any, B] = Http.fromFunctionZIO(_ => effect)

/**
* Creates an HTTP app which always responds with the provided Html page.
Expand Down Expand Up @@ -535,12 +530,12 @@ object Http {
/**
* Converts a ZIO to an Http app type
*/
def responseZIO[R, E](res: ZIO[R, E, Response]): HttpApp[R, E] = Http.fromEffect(res)
def responseZIO[R, E](res: ZIO[R, E, Response]): HttpApp[R, E] = Http.fromZIO(res)

/**
* Creates an Http that delegates to other Https.
*/
def route[A]: Http.MakeRoute[A] = Http.MakeRoute(())
def route[A]: Http.PartialRoute[A] = Http.PartialRoute(())

/**
* Creates an HTTP app which always responds with the same status code and empty data.
Expand Down Expand Up @@ -569,35 +564,31 @@ object Http {
def tooLarge: HttpApp[Any, Nothing] = Http.status(Status.REQUEST_ENTITY_TOO_LARGE)

// Ctor Help
final case class MakeCollectZIO[A](unit: Unit) extends AnyVal {
final case class PartialCollectZIO[A](unit: Unit) extends AnyVal {
def apply[R, E, B](pf: PartialFunction[A, ZIO[R, E, B]]): Http[R, E, A, B] =
Http.collect[A] { case a if pf.isDefinedAt(a) => Http.fromEffect(pf(a)) }.flatten
Http.collect[A] { case a if pf.isDefinedAt(a) => Http.fromZIO(pf(a)) }.flatten
}

final case class MakeCollect[A](unit: Unit) extends AnyVal {
final case class PartialCollect[A](unit: Unit) extends AnyVal {
def apply[B](pf: PartialFunction[A, B]): Http[Any, Nothing, A, B] = Collect(pf)
}

final case class MakeCollectHttp[A](unit: Unit) extends AnyVal {
final case class PartialCollectHttp[A](unit: Unit) extends AnyVal {
def apply[R, E, B](pf: PartialFunction[A, Http[R, E, A, B]]): Http[R, E, A, B] =
Http.collect[A](pf).flatten
}

final case class MakeFromEffectFunction[A](unit: Unit) extends AnyVal {
def apply[R, E, B](f: A => ZIO[R, E, B]): Http[R, E, A, B] = Http.FromEffectFunction(f)
}

final case class MakeRoute[A](unit: Unit) extends AnyVal {
final case class PartialRoute[A](unit: Unit) extends AnyVal {
def apply[R, E, B](pf: PartialFunction[A, Http[R, E, A, B]]): Http[R, E, A, B] =
Http.collect[A] { case r if pf.isDefinedAt(r) => pf(r) }.flatten
}

final case class MkContraFlatMap[-R, +E, -A, +B, X](self: Http[R, E, A, B]) extends AnyVal {
final case class PartialContraFlatMap[-R, +E, -A, +B, X](self: Http[R, E, A, B]) extends AnyVal {
def apply[R1 <: R, E1 >: E](xa: X => Http[R1, E1, Any, A]): Http[R1, E1, X, B] =
Http.identity[X].flatMap(xa) >>> self
}

final class FromOptionFunction[A](val unit: Unit) extends AnyVal {
final class PartialFromOptionFunction[A](val unit: Unit) extends AnyVal {
def apply[R, E, B](f: A => ZIO[R, Option[E], B]): Http[R, E, A, B] = Http
.collectZIO[A] { case a =>
f(a).map(Http.succeed(_)).catchAll {
Expand All @@ -608,12 +599,12 @@ object Http {
.flatten
}

final class FromFunction[A](val unit: Unit) extends AnyVal {
final class PartialFromFunction[A](val unit: Unit) extends AnyVal {
def apply[B](f: A => B): Http[Any, Nothing, A, B] = Http.identity[A].map(f)
}

final class FromFunctionZIO[A](val unit: Unit) extends AnyVal {
def apply[R, E, B](f: A => ZIO[R, E, B]): Http[R, E, A, B] = Http.identity[A].mapZIO(f)
final class PartialFromFunctionZIO[A](val unit: Unit) extends AnyVal {
def apply[R, E, B](f: A => ZIO[R, E, B]): Http[R, E, A, B] = FromFunctionZIO(f)
}

private final case class Succeed[B](b: B) extends Http[Any, Nothing, Any, B]
Expand All @@ -622,7 +613,7 @@ object Http {

private final case class Fail[E](e: E) extends Http[Any, E, Any, Nothing]

private final case class FromEffectFunction[R, E, A, B](f: A => ZIO[R, E, B]) extends Http[R, E, A, B]
private final case class FromFunctionZIO[R, E, A, B](f: A => ZIO[R, E, B]) extends Http[R, E, A, B]

private final case class Collect[R, E, A, B](ab: PartialFunction[A, B]) extends Http[R, E, A, B]

Expand Down
8 changes: 4 additions & 4 deletions zio-http/src/main/scala/zhttp/socket/Socket.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,21 @@ sealed trait Socket[-R, +E, -A, +B] { self =>
}

object Socket {
def collect[A]: MkCollect[A] = new MkCollect[A](())
def collect[A]: PartialCollect[A] = new PartialCollect[A](())

def end: ZStream[Any, Nothing, Nothing] = ZStream.halt(Cause.empty)

def fromFunction[A]: MkFromFunction[A] = new MkFromFunction[A](())
def fromFunction[A]: PartialFromFunction[A] = new PartialFromFunction[A](())

def fromStream[R, E, B](stream: ZStream[R, E, B]): Socket[R, E, Any, B] = FromStream(stream)

def succeed[A](a: A): Socket[Any, Nothing, Any, A] = Succeed(a)

final class MkFromFunction[A](val unit: Unit) extends AnyVal {
final class PartialFromFunction[A](val unit: Unit) extends AnyVal {
def apply[R, E, B](f: A => ZStream[R, E, B]): Socket[R, E, A, B] = FromStreamingFunction(f)
}

final class MkCollect[A](val unit: Unit) extends AnyVal {
final class PartialCollect[A](val unit: Unit) extends AnyVal {
def apply[R, E, B](pf: PartialFunction[A, ZStream[R, E, B]]): Socket[R, E, A, B] = Socket.FromStreamingFunction {
a =>
if (pf.isDefinedAt(a)) pf(a) else ZStream.empty
Expand Down
8 changes: 4 additions & 4 deletions zio-http/src/test/scala/zhttp/http/HExitSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ object HExitSpec extends DefaultRunnableSpec with HExitAssertion {
empty === isEmpty &&
succeed(1) === isSuccess(equalTo(1)) &&
fail(1) === isFailure(equalTo(1)) &&
effect(UIO(1)) === isEffect
fromZIO(UIO(1)) === isEffect
} +
test("flatMapError") {
succeed(0) *> fail(1) <> fail(2) === isFailure(equalTo(2)) &&
Expand All @@ -38,9 +38,9 @@ object HExitSpec extends DefaultRunnableSpec with HExitAssertion {
empty <+> empty === isEmpty
} +
test("effect") {
effect(UIO(1)) <+> empty === isEffect &&
empty <+> effect(UIO(1)) === isEffect &&
empty *> effect(UIO(1)) *> effect(UIO(1)) === isEmpty
fromZIO(UIO(1)) <+> empty === isEffect &&
empty <+> fromZIO(UIO(1)) === isEffect &&
empty *> fromZIO(UIO(1)) *> fromZIO(UIO(1)) === isEmpty
} +
test("nested succeed") {
empty <+> succeed(1) <+> succeed(2) === isSuccess(equalTo(1)) &&
Expand Down
Loading

1 comment on commit 00feb56

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance Benchmark:

Concurrency: 256
Requests/sec: 838318.39

Please sign in to comment.