Thursday, January 29, 2009

Error Messages in the PLT Scheme Web Server

I've just committed what I hope is a very useful addition to the PLT Web Server.

Previously, if there was a problem with the syntax of the HTML code in your servlet, you would get an opaque error, such as:

You broke the contract (-> request response) on start; expected <response?>, given: (html (head ...

And you would have little clue what the problem with it was.

Now, the Web Server will reformat your response and annotate it will all of its problems, then display that back to you.

A sample is available online.

Notice that all the errors are highlighted in red and when you hover over them, an explanation is given.

If you would like to try at home, get the latest SVN and try out the following servlet:

#lang web-server/insta
(define (start req)
  `(html (head (title "Hey"))
         (body
          nbsp
          ; Error 1
          ()
          ; Error 2
          ("foo")
          ; Error 3
          #f
          ; Error 4
          (p . #f)
          ; Error 5
          (span ([href "#"] . #f) nbsp)
          ; Error 6
          (span ([href #f]) nbsp)
          ; Error 7
          (span ([#f "#"]) nbsp)
          ; Error 8
          (span ([href "#"] #f) nbsp))))

Sunday, January 18, 2009

Load Control in the PLT Scheme Web Server

I've recently added a new dispatcher to the PLT Web Server: dispatchers/limit.

It allows you to limit the number of concurrent requests handled by a particular sub-dispatcher. For example, you could limit the number of active servlet requests, but have limitless file-system requests. The documentation gives a good example of using it.

One of the interesting features is the ability to control what happens to requests that occur after the limit has been exceeded. You can choose to (a) make them wait until there is space, (b) cause them to instantly fail, or (c) kill old request handlers and prioritize the new ones.


The code that implements this dispatcher is a good example of using the synchronization primitives of PLT Scheme (inherited from Concurrent ML.) Take a look at the code. You'll notice a few things:

  • The manager of the resources is abstracted into a separate thread, created at the time the dispatcher is constructed.
  • The users of limited dispatcher communicate with the manager through private synchronized channels that are invisible to the rest of the Web Server.
  • When a limit request is made, it is sent to the manager with a new first-class reply channel, so that the thread can receive a go-ahead to continue. Notice that this is not the case when the limited request completes: it doesn't need to wait for confirmation.
  • Because the channels of communication to the limit manager are completely controlled in this short function, the users can be relied upon to implement the load-shedding behavior. (See how if the reply channel communicates false, then the thread errors, freeing up resources.)
  • The manager is implemented as tail-recursive loop, storing the changing state (the current limit and the active requests) in lexical variables.
  • The sync function is repeatedly called to decide what activities the manager does at each step. sync will choose one of the available events each time it is called.
  • Based on whether the limit has reached it maximums, the manager chooses between allowing new requests in, or implementing the over-limit behavior. It can cause the new threads to block simply by ignoring the incoming request channel (implemented by returning the never-evt, rather than a handler based on it.
  • In either case, the manager will wait for requests to finalize and free-up their resources.
  • Because request handlers might die unexpectedly if their connection to the Web client is broken, the manager needs to monitor active threads and free their resources if they die. Therefore, it constructs an event for each partner that handles that partners death. This is why we use apply to call sync, rather than calling it directly.

This dispatcher would be much more painful to implement if we did not have the ability to use first-class channels, closures, variable-arity functions, or CML-style synchronization operators.

Thursday, January 1, 2009

Resolute

I've never really done New Year's Resolutions before, but after reading Angela's blog post about them, I was attracted to a few of hers, so I will get into the spirit this year.

Here are my resolutions:

  1. No refined sugar or corn syrup: Refined sugar is a poison and I think I am clearly addicted to it if I have something sweet every single day. This will also help me eat more fruit and vegetables, because I will likely snack on them, rather than sugary things.
  2. Grains... Grains...: I will eat fibrous grains at every meal. The average American apparently has 4 grams of fiber a day, when they should have 50.
  3. Limit TV Show Watching: Libby and I don't have access to live television, but we often get DVDs of shows. Like most people, cliff-hangers really get us and we often watch many episodes in a row. So, we will only watch movie-length amounts of shows, meaning a maximum of 3 episodes for a show like Buffy (which is our current show.)
  4. More Exercise: Every morning I do crunches and push-ups, but I used to do more daily exercises. (For example, I used to have a particular weight-lifting regime, but I lost my weights in our move from MA.) So, I'm bringing back some of these.

Should be fun!