Context in Scala

Here’s the translation of the Go code to Scala, along with explanations in Markdown format suitable for Hugo:

In the previous example we looked at setting up a simple HTTP server. HTTP servers are useful for demonstrating the usage of cancellation control. In Scala, we can use Future for handling asynchronous operations and Promise for cancellation signals.

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer

import scala.concurrent.{ExecutionContext, Future, Promise}
import scala.concurrent.duration._
import scala.util.{Failure, Success}

object ContextExample extends App {
  implicit val system = ActorSystem()
  implicit val materializer = ActorMaterializer()
  implicit val executionContext: ExecutionContext = system.dispatcher

  def hello(cancellationPromise: Promise[Unit]): Route = {
    path("hello") {
      get {
        println("server: hello handler started")
        val result = Future {
          Thread.sleep(10000)
          "hello\n"
        }

        val timeoutFuture = akka.pattern.after(10.seconds, using = system.scheduler) {
          Future.successful("hello\n")
        }

        onComplete(Future.firstCompletedOf(Seq(result, timeoutFuture, cancellationPromise.future))) {
          case Success(message) =>
            println("server: hello handler ended")
            complete(HttpEntity(ContentTypes.`text/plain(UTF-8)`, message))
          case Failure(ex) =>
            println(s"server: ${ex.getMessage}")
            complete(HttpResponse(StatusCodes.InternalServerError, entity = ex.getMessage))
        }
      }
    }
  }

  val cancellationPromise = Promise[Unit]()
  val bindingFuture = Http().bindAndHandle(hello(cancellationPromise), "localhost", 8090)

  println(s"Server online at http://localhost:8090/")
  println("Press RETURN to stop...")
  scala.io.StdIn.readLine()

  cancellationPromise.trySuccess(())
  bindingFuture
    .flatMap(_.unbind())
    .onComplete(_ => system.terminate())
}

In this Scala example, we’re using Akka HTTP to set up a simple HTTP server. The hello function defines a route that simulates some work by sleeping for 10 seconds before responding.

We use a Promise to represent a cancellation signal. This is passed to the hello function, allowing us to cancel the operation from outside.

The Future.firstCompletedOf is used to race between the actual work, a timeout, and the cancellation signal. Whichever completes first will determine the response.

To run the server:

$ sbt run

Simulate a client request to /hello, hitting Ctrl+C shortly after starting to signal cancellation:

$ curl http://localhost:8090/hello
server: hello handler started
^C
server: Operation cancelled
server: hello handler ended

This example demonstrates how to handle long-running operations in a web server context, with the ability to cancel operations and handle timeouts. While Scala doesn’t have a direct equivalent to Go’s context.Context, we can achieve similar functionality using Futures and Promises.