Context in Racket

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

In this example, we’ll demonstrate how to create a simple HTTP server in Racket and use continuation marks to simulate the behavior of context in handling cancellation.

#lang racket

(require web-server/servlet
         web-server/servlet-env
         web-server/http)

(define (hello request)
  (define mark-key 'request-context)
  (define continuation-mark (current-continuation-marks))
  
  (displayln "server: hello handler started")
  
  (define (cleanup)
    (displayln "server: hello handler ended"))
  
  (with-handlers ([exn:break? (lambda (exn)
                                (cleanup)
                                (displayln "server: request canceled")
                                (response/output
                                 (lambda (out)
                                   (fprintf out "Internal Server Error"))))])
    (define result
      (sync/timeout
       10
       (thread
        (lambda ()
          (sleep 10)
          "hello\n"))))
    
    (cleanup)
    (if result
        (response/output
         (lambda (out)
           (fprintf out result)))
        (raise (exn:break "timeout" continuation-mark)))))

(define (start request)
  (hello request))

(serve/servlet
 start
 #:port 8090
 #:servlet-regexp #rx"")

In this Racket implementation:

  1. We use the web-server library to create an HTTP server.

  2. The hello function simulates the behavior of the original Go example:

    • It prints a start message and sets up a cleanup function.
    • It uses sync/timeout to wait for 10 seconds or until the request is canceled.
    • If the request completes, it sends “hello” as the response.
    • If the request is canceled or times out, it raises an exception.
  3. We use continuation marks to simulate the context behavior. In Racket, continuation marks can be used to attach information to the current continuation, which is similar to how context works in the original example.

  4. The with-handlers expression catches any exn:break exceptions (which simulate cancellation) and returns an appropriate error response.

  5. The start function is the entry point for our server, which simply calls hello.

  6. Finally, we start the server using serve/servlet on port 8090.

To run the server:

$ racket context.rkt

You can then simulate a client request:

$ curl localhost:8090

If you interrupt the curl command (e.g., with Ctrl+C) before 10 seconds have passed, you should see the cancellation behavior.

Note that Racket’s web server and continuation marks provide a different approach to handling request contexts and cancellation compared to Go’s context package. This example demonstrates a way to achieve similar functionality, but the exact behavior and performance characteristics may differ.