Review Board 1.5.4

Async REST support

Updated 1 year, 10 months ago

Marius Danciu Reviewers
401 dpp, marius, charles, joni, atsuhiko, jorge, naftoli, kris, indrajit, alexb, dlouwers, mstarzyk, rmellgren, jhoffman, probinett, jmadsen, mhartmann, jstrachan, jgoday
None LiftWeb-archive
Some details are here: https://www.assembla.com/spaces/liftweb/tickets/401?batch=false&tickets_report_id=1&ticket_id=401&commit=Go+ยป
but I adopted a slightly different API. The way to use it is:

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

    }

    LiftRules.dispatch.append(continuation);

The point is that you pass to respondAsync a function that takes a single argument. This is the function that you need to call to send down the response asynchronously. Once the response is sent to client the next subsequent request will cause your function to be called again. If the container does not support the continuation idiom then locking is utilized and a thread is being held until the response is ready or timeout occurs (... you know the story).
testted with Jeyy 6, jetty 7 and with non continuations support.
Posted 1 year, 10 months ago (March 27th, 2010, 10:52 p.m.)
Actually I'll try to simplify the API a bit more ...
Review request changed
Updated 1 year, 10 months ago (March 28th, 2010, 12:21 a.m.)
ok .. made it simpler:

    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);
Posted 1 year, 10 months ago (March 29th, 2010, 1:21 a.m.)
Nice! Does the implementor need to create their own handler for object delta's and such? 
  1. Please define "object deltas". This concept is not very applicable here as we're dealing with generic LiftResponse-s. As I said, once the response is being sent to client the next subsequent client request will cause your function to be called again. How you compute your LiftResponse is implementation specific.
    
    However if you have specific use-cases in mind, please let me know.
  2. Hmm good point. What is the use case for comet-rest in general? I know we spoke about it at length and i do think its a good idea im just trying to remember what we said it could be used for? 
  3. To expose a Comet interface to the public via an API, I would say. The idea, of course, is that API consumers aren't constantly hitting your API asking for updates and when updates occur they are sent to the consumers faster. For example Twitter offers one: http://apiwiki.twitter.com/Streaming-API-Documentation.
  4. Well it's easy to envision the need to API's that push information for remote clients (not necessarily browsers) regardless of the data formatting protocol. For instance a client makes a REST request to server that need to perform an expensive operation. Although the execution of such operation can take minutes or hours or whatever, during such execution it is very helpful to be able to report back to client the progress for such processing. I'm dealing currently at work with such use-case I have expensive processing on server side that can also run in hadoop. It's easy to imagine that this is quite an expensive operation but I still need to report progress. The approach I took is something like:
    
    1. URL1 - Have an API for starting the processing. This is started asynchronously and the call returns immediately with a status.
    2. Client starts listening on the progress by sending requests to URL2 on a separated thread. Once it gets a response or times out it immediately sends the same request again listening for the next message until operation completion is reported or an error occurred.
    
    P.S. Unfortunately I have this in Java projects not in Scala. The demo app that I build exposing progress bars etc. is Lift ;) but other 3rd party application is using this server to monitor progress and working great.
  5. I could figure that much out for myself Peter ;-) Didn't know twitter had one now though... thanks for the link. Ok, good to go from my POV.
Ship it!
Posted 1 year, 10 months ago (March 29th, 2010, 1:54 a.m.)

   

  
Posted 1 year, 10 months ago (March 30th, 2010, 2:34 a.m.)
Any other opinions?
  1. I started through it but did not finish reviewing. If you'd like another review, I can do this when I get home tonight (about 10 hours from now)
    
  2. Excellent. Thanks.
Ship it!
Posted 1 year, 10 months ago (March 30th, 2010, 11:16 p.m.)
Code looks good to me, though I confess I'm not that familiar with the continuations API.

I found some minor typos in doc comments and a bit of indentation oddness.
asyynchronously -> asynchronously
functino -> function
continuztion -> continuation
asyynchronously -> asynchronously
functino -> function
body should be indented
indented one column too many
body should be indented
  1. Thanks a bunch Ross for pointing these out. I'll correct them before committing.