AJAX Request deduplication, take 2 #1328

merged 8 commits into from Oct 11, 2012
Commits on Sep 24, 2012
  1. Move uriSuffix extraction into lift_ajaxHandler.

    Shadowfiend committed Sep 24, 2012
    By having it in doAjaxCycle, there were situations where the uri suffix
    could get lost. The most obvious one was when a long-running ajax
    request was occurring, and two AJAX requests were queued during that
    time frame. This would result in the first request getting the second
    request's uriSuffix, and the second request getting no suffix at all.
    We now immediately put the uriSuffix into the sending data when
    lift_ajaxHandler is called.
  2. Encode an AJAX request version in the request URI.

    Shadowfiend committed Sep 24, 2012
    The AJAX request version has two components: the actual version number
    and a count of queued requests. This is presented as two base-36 values
    after a dash. So a request now looks like:
    /ajax_request/F<page version>-v8
    Where v indicates request number 31 and 8 indicates that there are 8
    queued requests that have not been handled yet.
  3. Drop the timeout on comet-related AJAX requests.

    Shadowfiend committed Sep 24, 2012
    While this will tie up a request thread for longer, it means we can
    reliably say that when the AJAX request thread completes, it will
    actually have the correct response to the original request.
  4. Add tracking for AJAX requests in LiftSession.

    Shadowfiend committed Sep 24, 2012
    Request info consists of three things:
     - The request version.
     - A future for the response to the request, satisfied by the first
       request for this version when the response is ready.
     - A lastSeen timestamp, used to expire the entry after the usual
       function lifespan.
    LiftSession.withAjaxRequests exposes the request list, which is a Map
    mapping a page version to the list of AjaxRequestInfos currently being
    tracked for that page. AjaxRequestInfos are cleaned up according to
    their lastSeen timestamp, which is updated the same way as those of
    functions on the page.
  5. Implement the meat of AJAX deduplication.

    Shadowfiend committed Sep 24, 2012
    AJAX requests now come in with a two-part version number, one a sequence
    number for the ajax request's count in the overall list of requests sent
    by the client, and one a number indicating how many other requests are
    queued up on the client.
    If this is the first request seen with its sequence number, we record
    the request in the session and run regular AJAX request handling. When
    that request handling is complete, it satisfies the future that is
    recorded in the session. Subsequent requests for a given sequence number
    wait on the future from the first request up to the ajax post timeout,
    then fail.
    When we get a request coming in with a 0 count for pending requests on
    the client, we clear out all other pending requests in the session's
    list, since that means none of them will be getting a chance to report
    their responses again.
Commits on Sep 28, 2012
  1. Track sequence numbers of arbitrary length.

    Shadowfiend committed Sep 28, 2012
    We track sequence numbers as Longs now, and the client side encodes the
    sequence number as an arbitrarily-long base-36 number.
  2. Guard for JS number size overflows.

    Shadowfiend committed Sep 28, 2012
    If you hit the maximum of a JS integer, math starts getting wonky. We
    make sure at that point we wrap to 0.
Commits on Oct 2, 2012
  1. Make AjaxRequestInfo track a Long version id.

    Shadowfiend committed Oct 2, 2012
    Not sure how I got this to compile locally without this change...