Skip to content

Commit

Permalink
Scope handling for handlers (#3197)
Browse files Browse the repository at this point in the history
  • Loading branch information
987Nabil committed Feb 3, 2025
1 parent b61ed97 commit 5ccb804
Show file tree
Hide file tree
Showing 38 changed files with 157 additions and 125 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ jobs:

- uses: actions/checkout@v4
with:
repository: khajavi/FrameworkBenchmarks
repository: zio/FrameworkBenchmarks
path: FrameworkBenchMarks

- id: result
Expand Down Expand Up @@ -1010,7 +1010,7 @@ jobs:

- uses: actions/checkout@v4
with:
repository: khajavi/FrameworkBenchmarks
repository: zio/FrameworkBenchmarks
path: FrameworkBenchMarks

- id: result
Expand Down
2 changes: 1 addition & 1 deletion project/BenchmarkWorkFlow.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ object BenchmarkWorkFlow {
WorkflowStep.Use(
UseRef.Public("actions", "checkout", s"v4"),
Map(
"repository" -> "khajavi/FrameworkBenchmarks",
"repository" -> "zio/FrameworkBenchmarks",
"path" -> "FrameworkBenchMarks",
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -674,15 +674,15 @@ class EndpointBenchmark {
http4sRequestFromString(url),
)

def unsafeRun[E, A](zio: ZIO[Any, E, A]): Unit = Unsafe.unsafe { implicit unsafe =>
def unsafeRun[E, A](z: ZIO[zio.Scope, E, A]): Unit = Unsafe.unsafe { implicit unsafe =>
Runtime.default.unsafe
.run(zio.unit)
.run(ZIO.scoped(z.unit))
.getOrThrowFiberFailure()
}

private def unsafeRunResult[E, A](zio: ZIO[Any, E, A]): A = Unsafe.unsafe { implicit unsafe =>
private def unsafeRunResult[E, A](z: ZIO[zio.Scope, E, A]): A = Unsafe.unsafe { implicit unsafe =>
Runtime.default.unsafe
.run(zio)
.run(ZIO.scoped(z))
.getOrThrowFiberFailure()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class HttpRouteTextPerf {
private val res = Response.text("HELLO WORLD")
private val app = Handler.succeed(res)
private val req: Request = Request.get(URL(Path.root))
private val httpProgram = ZIO.foreachDiscard(0 to 1000) { _ => app(req) }
private val httpProgram = ZIO.scoped(ZIO.foreachDiscard(0 to 1000) { _ => app(req) })
private val UIOProgram = ZIO.foreachDiscard(0 to 1000) { _ => ZIO.succeed(res) }

@Benchmark
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ object CounterProtocolStackExample extends ZIOAppDefault {
_ <- handler("What is ZIO?").debug
} yield ()

def run = app.provide(ZLayer.fromZIO(Ref.make(0L)))
def run = app.provide(Scope.default, ZLayer.fromZIO(Ref.make(0L)))
}
2 changes: 1 addition & 1 deletion zio-http-testkit/src/main/scala/zio/http/TestClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ final case class TestClient(
body: Body,
sslConfig: Option[zio.http.ClientSSLConfig],
proxy: Option[Proxy],
)(implicit trace: Trace): ZIO[Any, Throwable, Response] = {
)(implicit trace: Trace): ZIO[Scope, Throwable, Response] = {
for {
currentBehavior <- behavior.get.map(_ :+ Method.ANY / trailing -> handler(Response.notFound))
request = Request(
Expand Down
2 changes: 1 addition & 1 deletion zio-http-testkit/src/main/scala/zio/http/TestServer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ final case class TestServer(driver: Driver, bindPort: Int) extends Server {
_ <- driver.addApp(provided, r)
} yield ()

override def install[R](routes: Routes[Scope & R, Response])(implicit
override def install[R](routes: Routes[R, Response])(implicit
trace: zio.Trace,
tag: EnvironmentTag[R],
): URIO[R, Unit] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private[zio] final case class NettyDriver(
)
} yield StartResult(port, serverInboundHandler.inFlightRequests)

override def addApp[R](newApp: Routes[Scope & R, Response], env: ZEnvironment[R])(implicit trace: Trace): UIO[Unit] =
def addApp[R](newApp: Routes[R, Response], env: ZEnvironment[R])(implicit trace: Trace): UIO[Unit] =
ZIO.fiberId.map { fiberId =>
var loop = true
while (loop) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ private[zio] final case class ServerInboundHandler(
private def attemptImmediateWrite(
ctx: ChannelHandlerContext,
method: Method,
exit: ZIO[Any, Response, Response],
exit: ZIO[Scope, Response, Response],
): Boolean = {
exit match {
case Exit.Success(response) if response ne null =>
Expand Down Expand Up @@ -282,7 +282,7 @@ private[zio] final case class ServerInboundHandler(
ZIO.suspend {
val nettyChannel = NettyChannel.make[JWebSocketFrame](ctx.channel())
val webSocketChannel = WebSocketChannel.make(nettyChannel, queue, handshakeCompleted)
webSocketApp.handler.runZIO(webSocketChannel).ignoreLogged.forkDaemon
ZIO.scoped(webSocketApp.handler.runZIO(webSocketChannel)).ignoreLogged.forkDaemon
}
}
_ <- ZIO.attempt {
Expand Down Expand Up @@ -311,7 +311,7 @@ private[zio] final case class ServerInboundHandler(
private def writeResponse(
ctx: ChannelHandlerContext,
runtime: NettyRuntime,
exit: ZIO[Any, Response, Response],
exit: ZIO[Scope, Response, Response],
req: Request,
)(ensured: () => Unit): Unit = {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ object ClientConnectionSpec extends RoutesRunnableSpec {
serve.as(tests)
}
.provideShared(
Scope.default,
DynamicServer.live,
serverTestLayer,
Client.live,
Expand Down
2 changes: 1 addition & 1 deletion zio-http/jvm/src/test/scala/zio/http/ClientSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,6 @@ object ClientSpec extends RoutesRunnableSpec {
override def spec = {
suite("Client") {
serve.as(List(clientSpec))
}.provideShared(DynamicServer.live, serverTestLayer, Client.default) @@ sequential @@ withLiveClock
}.provideShared(Scope.default, DynamicServer.live, serverTestLayer, Client.default) @@ sequential @@ withLiveClock
}
}
2 changes: 1 addition & 1 deletion zio-http/jvm/src/test/scala/zio/http/ContentTypeSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,6 @@ object ContentTypeSpec extends RoutesRunnableSpec {
override def spec = {
suite("Content-type") {
serve.as(List(contentSpec))
}.provideShared(DynamicServer.live, serverTestLayer, Client.default) @@ withLiveClock @@ sequential
}.provideShared(Scope.default, DynamicServer.live, serverTestLayer, Client.default) @@ withLiveClock @@ sequential
}
}
2 changes: 1 addition & 1 deletion zio-http/jvm/src/test/scala/zio/http/FlashSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ object FlashSpec extends ZIOHttpSpec {
)
bodyString <- response2.body.asString
} yield assertTrue(bodyString.contains("successfully") && bodyString.contains("green"))
}.provideLayer(Flash.Backend.inMemory),
}.provide(Scope.default, Flash.Backend.inMemory),
)

}
4 changes: 2 additions & 2 deletions zio-http/jvm/src/test/scala/zio/http/HandlerAspectSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ object HandlerAspectSpec extends ZIOSpecDefault {
//can't be infix because of Scala 3
}.@@[Boolean](handlerAspect)
for {
response <- handler0(Request(headers = Headers("accept", "*"))).provideEnvironment(ZEnvironment(true))
response <- ZIO.scoped(handler0(Request(headers = Headers("accept", "*")))).provideEnvironment(ZEnvironment(true))
bodyString <- response.body.asString
} yield assertTrue(bodyString == "1")
},
Expand All @@ -41,7 +41,7 @@ object HandlerAspectSpec extends ZIOSpecDefault {
//can't be infix because of Scala 3
}.@@[Boolean](handlerAspect)
for {
response <- handler0(Request(headers = Headers("accept", "*"))).provideEnvironment(ZEnvironment(true) ++ ZEnvironment("test"))
response <- ZIO.scoped(handler0(Request(headers = Headers("accept", "*")))).provideEnvironment(ZEnvironment(true) ++ ZEnvironment("test"))
bodyString <- response.body.asString
} yield assertTrue(bodyString == "1 test")
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ object HybridRequestStreamingServerSpec extends RoutesRunnableSpec {
appWithHybridReqStreaming.as(List(requestBodySpec, hybridStreamingServerSpec))
}
}.provideShared(
Scope.default,
DynamicServer.live,
ZLayer.succeed(configAppWithHybridRequestStreaming),
Server.customized,
Expand Down
2 changes: 1 addition & 1 deletion zio-http/jvm/src/test/scala/zio/http/KeepAliveSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ object KeepAliveSpec extends RoutesRunnableSpec {
override def spec: Spec[Any, Throwable] = {
suite("KeepAliveSpec") {
keepAliveSpec
}.provide(DynamicServer.live, serverTestLayer, Client.default) @@ withLiveClock @@ sequential
}.provide(Scope.default, DynamicServer.live, serverTestLayer, Client.default) @@ withLiveClock @@ sequential
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,5 @@ object RoutesMiddlewareSpec extends ZIOHttpSpec with ExitAssertion {
result2 <- ref.get
} yield assertTrue(result1 == 1, result2 == 1)
},
)
).provide(Scope.default)
}
1 change: 1 addition & 0 deletions zio-http/jvm/src/test/scala/zio/http/ServerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ object ServerSpec extends RoutesRunnableSpec {
val spec = dynamicAppSpec + responseSpec + requestSpec + requestBodySpec + serverErrorSpec
suite("app without request streaming") { app.as(List(spec)) }
}.provideShared(
Scope.default,
DynamicServer.live,
ZLayer.succeed(configApp),
Server.customized,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ object StaticFileServerSpec extends RoutesRunnableSpec {

override def spec = suite("StaticFileServerSpec") {
serve.as(List(staticSpec))
}.provideShared(DynamicServer.live, serverTestLayer, Client.default) @@ withLiveClock @@ sequential
}.provideShared(Scope.default, DynamicServer.live, serverTestLayer, Client.default) @@ withLiveClock @@ sequential

private def staticSpec = suite("Static RandomAccessFile Server")(
suite("fromResource")(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ object EndpointSpec extends ZIOHttpSpec {
def testEndpoint[R](service: Routes[R, Nothing])(
url: String,
expected: String,
): ZIO[R, Response, TestResult] =
): ZIO[Scope & R, Response, TestResult] =
testEndpointWithHeaders(service)(url, headers = List.empty, expected)

def testEndpointWithHeaders[R](service: Routes[R, Nothing])(
url: String,
headers: List[(String, String)],
expected: String,
): ZIO[R, Response, TestResult] = {
): ZIO[Scope & R, Response, TestResult] = {
val request = Request
.get(url = URL.decode(url).toOption.get)
.addHeaders(headers.foldLeft(Headers.empty) { case (hs, (k, v)) => hs ++ Headers(k, v) })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ object NotFoundSpec extends ZIOHttpSpec {
def test404[R](service: Routes[R, Nothing])(
url: String,
method: Method,
): ZIO[R, Response, TestResult] = {
): ZIO[Scope & R, Response, TestResult] = {
val request = Request(method = method, url = URL.decode(url).toOption.get)
for {
response <- service.runZIO(request)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package zio.http.internal

import zio._
import zio.{EnvironmentTag, Scope, ZIO}

import zio.http.URL.Location
import zio.http._
Expand Down Expand Up @@ -111,9 +111,7 @@ abstract class RoutesRunnableSpec extends ZIOHttpSpec { self =>
_ <- DynamicServer.setStart(server)
} yield port

def serve[R: EnvironmentTag](
routes: Routes[Scope & R, Response],
): ZIO[R with DynamicServer with Server, Nothing, Int] =
def serve[R: EnvironmentTag](routes: Routes[R, Response]): ZIO[R with DynamicServer with Server, Nothing, Int] =
for {
server <- ZIO.service[Server]
port <- Server.install(routes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ object WebSpec extends ZIOHttpSpec with TestExtensions { self =>

private def runRoutes[R](routes: Routes[R, Response]): ZIO[R, Response, Response] = {
for {
fib <- routes.runZIO { Request.get(url = URL(Path.root / "health")) }.fork
fib <- ZIO.scoped[R](routes.runZIO { Request.get(url = URL(Path.root / "health")) }).fork
_ <- TestClock.adjust(10 seconds)
res <- fib.join
} yield res
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ object NettyConnectionPoolSpec extends RoutesRunnableSpec {
def connectionPoolTests(
version: Version,
casesByHeaders: Map[String, Headers],
): Spec[Client with DynamicServer, Throwable] =
): Spec[Scope & Client with DynamicServer, Throwable] =
suite(version.toString)(
casesByHeaders.map { case (name, extraHeaders) =>
suite(name)(
Expand Down Expand Up @@ -193,6 +193,7 @@ object NettyConnectionPoolSpec extends RoutesRunnableSpec {
),
)
}.provideSome[Client](
Scope.default,
ZLayer(appKeepAliveEnabled.unit),
DynamicServer.live,
ZLayer.succeed(Server.Config.default.idleTimeout(500.millis).onAnyOpenPort.logWarningOnFatalError(false)),
Expand All @@ -209,6 +210,7 @@ object NettyConnectionPoolSpec extends RoutesRunnableSpec {

ZIO.collectAll(List.fill(4)(f)).map(_.foldLeft(assertCompletes)(_ && _))
}.provide(
Scope.default,
ZLayer(appKeepAliveEnabled.unit),
DynamicServer.live,
ZLayer.succeed(Server.Config.default.idleTimeout(500.millis).onAnyOpenPort.logWarningOnFatalError(false)),
Expand Down Expand Up @@ -267,6 +269,7 @@ object NettyConnectionPoolSpec extends RoutesRunnableSpec {
} @@ ignore, // ZPool is broken in ZIO 2.1.9 should be fixed with 2.1.10
)
}.provide(
Scope.default,
ZLayer(appKeepAliveEnabled.unit),
DynamicServer.live,
serverTestLayer,
Expand Down Expand Up @@ -297,6 +300,7 @@ object NettyConnectionPoolSpec extends RoutesRunnableSpec {
connectionPoolTimeoutTest,
connectionPoolShutdownSpec,
).provide(
Scope.default,
ZLayer(appKeepAliveEnabled.unit),
DynamicServer.live,
serverTestLayer,
Expand Down Expand Up @@ -324,6 +328,7 @@ object NettyConnectionPoolSpec extends RoutesRunnableSpec {
connectionPoolTimeoutTest,
connectionPoolShutdownSpec,
).provide(
Scope.default,
ZLayer(appKeepAliveEnabled.unit),
DynamicServer.live,
serverTestLayer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ object ExceptionSpec extends ZIOSpecDefault {
} yield assertTrue(!response.contains("Exception in thread"))
},
).provide(
Scope.default,
Server.customized,
ZLayer.succeed(
Server.Config.default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ object TimingAttacksSpec extends ZIOSpecDefault {

val nOfTries = 1000

def runZ[A](a: ZIO[Any, Throwable, A]) =
def runZ[A](a: ZIO[Scope, Throwable, A]) =
Unsafe.unsafe { implicit unsafe =>
zio.Runtime.default.unsafe
.run(
a,
ZIO.scoped(a),
)
.getOrThrowFiberFailure()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ object UserDataSpec extends ZIOSpecDefault {
}
},
).provide(
Scope.default,
Server.customized,
ZLayer.succeed(
Server.Config.default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ trait HandlerVersionSpecific {
): Handler[Env0 with Env1, Response, Request, Response] =
aspect.applyHandlerContext {
handler { (ctx: Ctx, req: Request) =>
val handler: ZIO[Env, Response, Response] = self.asInstanceOf[Handler[Env, Response, Request, Response]](req)
val handler: ZIO[Env, Response, Response] =
self
.asInstanceOf[Handler[Env, Response, Request, Response]](req)
.asInstanceOf[ZIO[Env, Response, Response]]
handler.provideSomeEnvironment[Env0](_.add[Ctx](ctx).asInstanceOf[ZEnvironment[Env]])
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ trait HandlerVersionSpecific {
): Handler[Env0 with Env1, Response, Request, Response] =
aspect.applyHandlerContext {
handler { (ctx: Ctx, req: Request) =>
val handler: ZIO[Env, Response, Response] = self.asInstanceOf[Handler[Env, Response, Request, Response]](req)
val handler: ZIO[Env, Response, Response] =
self.asInstanceOf[Handler[Env, Response, Request, Response]](req)
.asInstanceOf[ZIO[Env, Response, Response]]
handler.provideSomeEnvironment[Env0](_.add(ctx).asInstanceOf[ZEnvironment[Env]])
}
}
Expand Down
2 changes: 1 addition & 1 deletion zio-http/shared/src/main/scala/zio/http/Driver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import zio.http.Driver.StartResult
trait Driver {
def start(implicit trace: Trace): RIO[Scope, StartResult]

def addApp[R](newRoutes: Routes[Scope & R, Response], env: ZEnvironment[R])(implicit trace: Trace): UIO[Unit]
def addApp[R](newRoutes: Routes[R, Response], env: ZEnvironment[R])(implicit trace: Trace): UIO[Unit]

def createClientDriver()(implicit trace: Trace): ZIO[Scope, Throwable, ClientDriver]
}
Expand Down
Loading

0 comments on commit 5ccb804

Please sign in to comment.