Skip to content

Commit

Permalink
Merge pull request #1638 from ChristopherDavenport/fixImmediatelyRetu…
Browse files Browse the repository at this point in the history
…rningServe

Fix immediately returning serve
  • Loading branch information
ChristopherDavenport committed Jan 24, 2018
2 parents 29671c0 + 3f9afe4 commit 7d3ebff
Show file tree
Hide file tree
Showing 8 changed files with 28 additions and 4 deletions.
2 changes: 1 addition & 1 deletion docs/src/main/tut/service.md
Expand Up @@ -52,7 +52,7 @@ Wherever you are in your studies, let's create our first
`HttpService`. Start by pasting these imports into your SBT console:

```tut:book
import cats.effect._, org.http4s._, org.http4s.dsl.io._
import cats.effect._, org.http4s._, org.http4s.dsl.io._, scala.concurrent.ExecutionContext.Implicits.global
```

Using the [http4s-dsl], we can construct an `HttpService` by pattern
Expand Down
Expand Up @@ -9,6 +9,7 @@ import org.http4s.HttpService
import org.http4s.server.blaze.BlazeBuilder
import org.http4s.server.metrics._
import org.http4s.server.{HttpMiddleware, Router}
import scala.concurrent.ExecutionContext.Implicits.global

object BlazeMetricsExample extends BlazeMetricsExampleApp[IO]

Expand Down
Expand Up @@ -6,6 +6,7 @@ import fs2.StreamApp.ExitCode
import org.http4s._
import org.http4s.dsl.Http4sDsl
import org.http4s.server.blaze.BlazeBuilder
import scala.concurrent.ExecutionContext.Implicits.global

object Example extends StreamApp[IO] with Http4sDsl[IO] {
val service: HttpService[IO] = HttpService[IO] {
Expand Down
Expand Up @@ -9,6 +9,7 @@ import org.http4s.dsl.Http4sDsl
import org.http4s.server.HttpMiddleware
import org.http4s.server.jetty.JettyBuilder
import org.http4s.server.metrics._
import scala.concurrent.ExecutionContext.Implicits.global

object JettyExample extends JettyExampleApp[IO]

Expand Down
Expand Up @@ -9,6 +9,7 @@ import fs2.{Scheduler, Stream, StreamApp}
import org.http4s.server.middleware.HSTS
import org.http4s.server.{SSLContextSupport, ServerBuilder}
import java.security.{KeyStore, Security}
import scala.concurrent.ExecutionContext.Implicits.global

abstract class SslClasspathExample[F[_]: Effect] extends StreamApp[F] {

Expand Down
Expand Up @@ -8,6 +8,7 @@ import java.nio.file.Paths
import org.http4s.server.SSLKeyStoreSupport.StoreInfo
import org.http4s.server.middleware.HSTS
import org.http4s.server.{SSLKeyStoreSupport, ServerBuilder}
import scala.concurrent.ExecutionContext.Implicits.global

abstract class SslExample[F[_]: Effect] extends StreamApp[F] {
// TODO: Reference server.jks from something other than one child down.
Expand Down
Expand Up @@ -8,6 +8,7 @@ import fs2.StreamApp.ExitCode
import org.http4s.server.HttpMiddleware
import org.http4s.server.metrics._
import org.http4s.server.tomcat.TomcatBuilder
import scala.concurrent.ExecutionContext.Implicits.global

object TomcatExample extends TomcatExampleApp[IO]

Expand Down
24 changes: 21 additions & 3 deletions server/src/main/scala/org/http4s/server/ServerBuilder.scala
@@ -1,12 +1,15 @@
package org.http4s
package server

import cats.implicits._
import cats.effect._
import fs2.StreamApp.ExitCode
import fs2._
import java.net.{InetAddress, InetSocketAddress}
import java.util.concurrent.ExecutorService
import javax.net.ssl.SSLContext
import fs2.async.immutable.Signal
import fs2.async.Ref
import org.http4s.server.SSLKeyStoreSupport.StoreInfo
import scala.collection.immutable
import scala.concurrent.ExecutionContext
Expand Down Expand Up @@ -53,10 +56,25 @@ trait ServerBuilder[F[_]] {
* Runs the server as a process that never emits. Useful for a server
* that runs for the rest of the JVM's life.
*/
final def serve(implicit F: Async[F]): Stream[F, ExitCode] =
final def serve(implicit F: Effect[F], ec: ExecutionContext): Stream[F, ExitCode] =
for {
signal <- Stream.eval(async.signalOf[F, Boolean](false))
exitCode <- Stream.eval(async.refOf[F, ExitCode](ExitCode.Success))
serve <- serveWhile(signal, exitCode)
} yield serve

/**
* Runs the server as a Stream that emits only when the terminated signal becomes true.
* Useful for servers with associated lifetime behaviors.
*/
final def serveWhile(
terminateWhenTrue: Signal[F, Boolean],
exitWith: Ref[F, ExitCode]): Stream[F, ExitCode] =
Stream.bracket(start)(
(_: Server[F]) => Stream.eval_(F.async[Unit](cb => cb(Right(())))),
_.shutdown)
(_: Server[F]) =>
terminateWhenTrue.discrete.takeWhile(_ === false).drain ++ Stream.eval(exitWith.get),
_.shutdown
)

/** Set the banner to display when the server starts up */
def withBanner(banner: immutable.Seq[String]): Self
Expand Down

0 comments on commit 7d3ebff

Please sign in to comment.