zio-http icon indicating copy to clipboard operation
zio-http copied to clipboard

Graceful shutdown pattern for the "Getting Started" or the "Simple Server" template...

Open chaotic3quilibrium opened this issue 2 years ago • 2 comments

In anticipation of bootstrapping a new zio-http server, I am using the "Getting Started" template to "grow" towards a solution as I am learning Zio and ZHttp. The current version of the "Getting Started" template looks like this, requiring that I externally "kill" the running process:

import zio.http._
import zio.http.Server
import zio._

object HelloWorld extends ZIOAppDefault {

  val app: HttpApp[Any, Nothing] = Http.collect[Request] {
    case Method.GET -> !! / "text" => Response.text("Hello World!")
  }

  override val run =
    Server.start(8090, app)
}

I would like to modify app by adding a "stop" command, and have the server process perform a "graceful shutdown".

  val app: HttpApp[Any, Nothing] = Http.collect[Request] {
    case Method.GET -> !! / "stop" => ???
    case Method.GET -> !! / "text" => Response.text("Hello World!")
  }

With what might I replace the ??? to achieve that outcome?

Or, if that isn't possible, what is the simplest pattern I could use to implement the desired "graceful shutdown"?

chaotic3quilibrium avatar Sep 18 '22 20:09 chaotic3quilibrium

@chaotic3quilibrium something similar to this should work:

  import zhttp._
  import zhttp.service.Server
  import zhttp.http.{ Request, Response }
  import zhttp.http._
  override def run =
    (for {
      shutdownSignal <- Promise.make[Nothing, Unit]
      app             = Http.collectZIO[Request] {
                          case Method.GET -> !! / "stop"   => shutdownSignal.succeed(()).as(Response.text("shutting down"))
                          case Method.GET -> !! / "health" => ZIO.succeed(Response.text("Ok"))
                        }
      server         <- Server.start(8080, app).fork
      _              <- shutdownSignal.await.flatMap(_ => ZIO.sleep(10.seconds) *> server.interrupt)
    } yield ()).provide(
      EventLoopGroup.auto(0),
      ServerChannelFactory.auto
    )

frekw avatar Sep 19 '22 11:09 frekw

Maybe we can add Server#stop method, which stops the server and releases resources early. Of course, this calls into question what Server#install should do in the event the server is already shut down.

jdegoes avatar Sep 19 '22 20:09 jdegoes