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.