Context in Lisp

Here’s the translation of the Go code to Lisp, formatted in Markdown suitable for Hugo:

(defpackage :context-example
  (:use :cl :hunchentoot :bordeaux-threads :local-time))

(in-package :context-example)

(defvar *server* (make-instance 'easy-acceptor :port 8090))

(defun hello-handler ()
  (format t "server: hello handler started~%")
  (finish-output)
  (let ((start-time (now)))
    (handler-case
        (progn
          (sleep 10)
          (format t "server: hello handler ended~%")
          (finish-output)
          "hello\n")
      (sb-sys:interactive-interrupt ()
        (let ((duration (timestamp-difference (now) start-time)))
          (format t "server: request canceled after ~A seconds~%" 
                  (timestamp-duration duration))
          (finish-output)
          (setf (return-code*) +http-internal-server-error+)
          (format nil "Request canceled after ~A seconds" 
                  (timestamp-duration duration)))))))

(define-easy-handler (hello :uri "/hello") ()
  (hello-handler))

(defun main ()
  (start *server*)
  (format t "Server started on port 8090~%")
  (finish-output)
  (sb-thread:join-thread 
   (find-if (lambda (th) 
              (string= (sb-thread:thread-name th) "hunchentoot-listener-*:8090"))
            (sb-thread:list-all-threads))))

In this Lisp example, we’re using the Hunchentoot web server to create an HTTP server that demonstrates handling long-running requests and cancellation.

The hello-handler function simulates a long-running operation that takes 10 seconds to complete. If the client cancels the request before it completes, we catch the interruption and return an appropriate error message.

Here’s how you might run and test this server:

  1. Start the server:
$ sbcl --load context-example.lisp
Server started on port 8090
  1. In another terminal, send a request and cancel it with Ctrl+C:
$ curl localhost:8090/hello
server: hello handler started
^C
  1. You should see output in the server terminal similar to:
server: hello handler started
server: request canceled after 2.1234 seconds

This example demonstrates how to handle long-running operations in a web server context, including proper cancellation handling. While Lisp doesn’t have a direct equivalent to Go’s context.Context, we achieve similar functionality using Lisp’s condition system and thread interrupts.

Note that this example uses SBCL-specific thread functions. If you’re using a different Common Lisp implementation, you may need to adjust the threading code accordingly.