目次

Version 4, last updated by Heiko Seeberger at Apr 07 22:45 UTC

COMET (otherwise known as long polling) support in Lift is certainly one of the most appealing features as it allows us to push messages from server to client asynchronously. This paradigm is also useful for REST API’s. One use-case would be when a REST invocation implies an expensive operation and the REST client wants to be notified with the operation progress.

To achieve this in Lift what we need to do is:

val continuation: LiftRules.DispatchPF = {
  case Req("cont" :: rest, _, _) => {
    S respondAsync {
      Thread.sleep(20000) // some computation here
      Full(XmlResponse(<async>response</async>))
    }
  }
}

LiftRules.dispatch.append(continuation);

Therefore when the request to /cont resource arrives, Lift invokes the function that you pass to responseAsync method. This invocation is done on a different thread. If the underlying web container supports suspend/resume idiom the control is passed to the container and your function continues running – no threads are being kept locked. When the computation is complete you just need to return a Box[LiftResponse]. Lift will make sure to propagate this response to the REST client.

Now, on the client side your REST client needs to send the REST request that would match your pattern. Whenever the client receives a response it would process it. However many times a true response may not b available thus an empty response is received. In this case the REST client should send immediately the same request to server. You can repeat this cycle as your API messages require to – such as until an expensive computation is complete. Note that such expensive computation is application dependent and it can take from seconds to hours or more.

If the underlying web container does not support suspend/resume idiom Lift will use a thread locking mechanism to achieve this effect. This of course does not scale as container’s threads are being locked until you send down a response.