Created
July 23, 2019 13:07
-
-
Save jamesanto/58b44fd630b502e95c8cccaadc27854d to your computer and use it in GitHub Desktop.
Generic Services & Filters based on Finagle, using ZIO
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.scalatest.{FreeSpec, Matchers} | |
class Filter2FilterTest extends FreeSpec with Matchers with ZioTestSupport { | |
case class JsonErr() | |
case class JsonReq() | |
case class JsonRes() | |
case class HttpErr() | |
case class HttpReq() | |
case class HttpRes() | |
case class DomainErr() | |
case class DomainReq() | |
case class DomainRes() | |
val http: Service[HttpErr, HttpReq, HttpRes] = Service.fromFunction { httpReq => | |
HttpRes() | |
} | |
val json: Filter[HttpErr, JsonErr, HttpReq, HttpRes, JsonReq, JsonRes] = { httpService => | |
Service.fromFunctionM { jsonReq => | |
//convert json req to http req | |
httpService | |
.provide(HttpReq()) | |
.map { httpRes => | |
JsonRes() | |
} | |
.mapError { httpErr => | |
JsonErr() | |
} | |
} | |
} | |
val domain: Filter[JsonErr, DomainErr, JsonReq, JsonRes, DomainReq, DomainRes] = { jsonService => | |
Service.fromFunctionM { domainReq => | |
//convert domain req to json req | |
jsonService | |
.provide(JsonReq()) | |
.map { jsonRes => | |
DomainRes() | |
} | |
.mapError { jsonErr => | |
DomainErr() | |
} | |
} | |
} | |
val filterStack: Service[HttpErr, HttpReq, HttpRes] => Service[DomainErr, DomainReq, DomainRes] = json >>> domain | |
val fullStack: Service[DomainErr, DomainReq, DomainRes] = filterStack >>> http | |
"should work properly" in { | |
val result = eval(fullStack.provide(DomainReq())) | |
result shouldBe Right(DomainRes()) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.scalatest.{FreeSpec, Matchers} | |
class Filter2ServiceTest extends FreeSpec with Matchers with ZioTestSupport { | |
case class HttpErr() | |
case class HttpReq() | |
case class HttpRes() | |
case class DomainErr() | |
case class DomainReq() | |
case class DomainRes() | |
val filter: Filter[HttpErr, DomainErr, HttpReq, HttpRes, DomainReq, DomainRes] = { httpService => | |
Service.fromFunctionM { domainReq => | |
//convert domain req to http req | |
httpService | |
.provide(HttpReq()) | |
.map { httpRes => | |
DomainRes() | |
} | |
.mapError { httpErr => | |
DomainErr() | |
} | |
} | |
} | |
val service: Service[HttpErr, HttpReq, HttpRes] = Service.fromFunction { httpReq => | |
//use http client here | |
HttpRes() | |
} | |
val stack: Service[DomainErr, DomainReq, DomainRes] = filter >>> service | |
"should work properly" in { | |
val result = eval(stack.provide(DomainReq())) | |
result shouldBe Right(DomainRes()) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import zio._ | |
package object service { | |
type Service[+Err, -Req, +Rep] = ZIO[Req, Err, Rep] | |
val Service: ZIO.type = ZIO | |
type Filter[InErr, OutErr, InReq, InRep, OutReq, OutRep] = | |
Service[InErr, InReq, InRep] => Service[OutErr, OutReq, OutRep] | |
type SimpleFilter0[InErr, OutErr, Req, Rep] = Filter[InErr, OutErr, Req, Rep, Req, Rep] | |
type SimpleFilter[Err, Req, Rep] = SimpleFilter0[Err, Err, Req, Rep] | |
implicit class RichFunction[-A, +B](val f: A => B) extends AnyVal { | |
def >>>(a: A): B = f(a) | |
def >>>[C](g: B => C): A => C = g.compose(f) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.scalatest.{FreeSpec, Matchers} | |
class Service2ServiceTest extends FreeSpec with Matchers with ZioTestSupport { | |
case class Err1() | |
case class Err2() | |
private val toInt: Service[Err1, String, Int] = Service.fromFunction(_.toInt) | |
private val toDouble: Service[Err2, Int, Double] = Service.fromFunction(_.toDouble) | |
private val failWithErr1: Service[Err1, String, Int] = Service.fail(Err1()) | |
private val failWithErr2: Service[Err2, Int, Double] = Service.fail(Err2()) | |
"should work properly" in { | |
val service = toInt >>> toDouble | |
val result = eval(service.provide("12")) | |
result shouldBe Right(12.0) | |
} | |
"should fail when first service fails" in { | |
val service = failWithErr1 >>> toDouble | |
val result = eval(service.provide("12")) | |
result shouldBe Left(Err1()) | |
} | |
"should fail when second service fails" in { | |
val service = toInt >>> failWithErr2 | |
val result = eval(service.provide("12")) | |
result shouldBe Left(Err2()) | |
} | |
"should fail with first error when both service fail" in { | |
val service = failWithErr1 >>> failWithErr2 | |
val result = eval(service.provide("12")) | |
result shouldBe Left(Err1()) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import zio.{DefaultRuntime, IO} | |
trait ZioTestSupport { | |
private val rt = new DefaultRuntime {} | |
def eval[E, A](io: IO[E, A]): Either[E, A] = { | |
rt.unsafeRun(io.either) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Refer this issue for details : zio/zio#1214