Skip to content

Commit

Permalink
Move ajax request list into LiftSession with lastSeen.
Browse files Browse the repository at this point in the history
LiftSession is in charge of managing cleanup of non-recently-seen pages
and such, so it needs to know about the AjaxRequestInfo list to clean it
up when a given request hasn't been needed in sufficiently long.
  • Loading branch information
Shadowfiend committed Aug 18, 2012
1 parent 1c46530 commit 7d89340
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 21 deletions.
31 changes: 10 additions & 21 deletions web/webkit/src/main/scala/net/liftweb/http/LiftServlet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -472,15 +472,7 @@ class LiftServlet extends Loggable {

private case class AjaxResponseComplete(response: Box[LiftResponse])

/**
* existingResponse is Empty if we have no response for this request
* yet. pendingActors is a list of actors who want to be notified when
* this response is received.
*/
private case class AjaxRequestInfo(requestVersion:Int, existingResponse:Box[Box[LiftResponse]], pendingActors:List[LiftActor])

private lazy val ajaxPostTimeout: Long = LiftRules.ajaxPostTimeout * 1000L
private val currentAjaxRequests = scala.collection.mutable.Map[String,AjaxRequestInfo]()

/**
* Runs the actual AJAX processing. This includes handling __lift__GC,
Expand Down Expand Up @@ -510,9 +502,6 @@ class LiftServlet extends Loggable {
val renderVersion = RenderVersion.get
liftSession.updateFuncByOwner(renderVersion, millis)

// FIXME We need to clean up currentAjaxRequests entries when
// FIXME the page expires.

Full(JavaScriptResponse(js.JsCmds.Noop))

case _ =>
Expand Down Expand Up @@ -626,36 +615,36 @@ class LiftServlet extends Loggable {
val renderVersion = RenderVersion.get

val toReturn: Box[Box[LiftResponse]] =
currentAjaxRequests.synchronized {
liftSession.withAjaxRequests { currentAjaxRequests =>
currentAjaxRequests.get(renderVersion).collect {
case AjaxRequestInfo(storedVersion, _, pendingActors) if handlerVersion != storedVersion =>
case AjaxRequestInfo(storedVersion, _, pendingActors, _) if handlerVersion != storedVersion =>
// Break out of any actors for the stale version.
pendingActors.foreach(_ ! BreakOut())

// Evict the older version's info.
currentAjaxRequests +=
(renderVersion ->
AjaxRequestInfo(handlerVersion, Empty, cont :: Nil))
AjaxRequestInfo(handlerVersion, Empty, cont :: Nil, millis))

suspendRequest()

Empty // no response available, triggers the actual AJAX computation below

case AjaxRequestInfo(storedVersion, existingResponseBox @ Full(_), _) =>
case AjaxRequestInfo(storedVersion, existingResponseBox @ Full(_), _, _) =>
existingResponseBox // return the Full response Box

case AjaxRequestInfo(storedVersion, _, pendingActors) =>
case AjaxRequestInfo(storedVersion, _, pendingActors, _) =>
currentAjaxRequests +=
(renderVersion ->
AjaxRequestInfo(handlerVersion, Empty, cont :: pendingActors))
AjaxRequestInfo(handlerVersion, Empty, cont :: pendingActors, millis))

suspendRequest()

Full(Full(EmptyResponse))
} openOr {
currentAjaxRequests +=
(renderVersion ->
AjaxRequestInfo(handlerVersion, Empty, cont :: Nil))
AjaxRequestInfo(handlerVersion, Empty, cont :: Nil, millis))

suspendRequest()

Expand All @@ -670,13 +659,13 @@ class LiftServlet extends Loggable {
// any waiting actors then clear the actor list and update the
// request info to include the response in case any other
// requests come in with this version.
currentAjaxRequests.synchronized {
liftSession.withAjaxRequests { currentAjaxRequests =>
currentAjaxRequests.get(renderVersion).collect {
case AjaxRequestInfo(storedVersion, _, pendingActors) if storedVersion == handlerVersion =>
case AjaxRequestInfo(storedVersion, _, pendingActors, _) if storedVersion == handlerVersion =>
pendingActors.foreach(_ ! AjaxResponseComplete(Full(result)))
currentAjaxRequests +=
(renderVersion ->
AjaxRequestInfo(handlerVersion, Full(Full(result)), Nil))
AjaxRequestInfo(handlerVersion, Full(Full(result)), Nil, millis))
}
}
})))
Expand Down
36 changes: 36 additions & 0 deletions web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,16 @@ private final case class PostPageFunctions(renderVersion: String,

}

/**
* existingResponse is Empty if we have no response for this request
* yet. pendingActors is a list of actors who want to be notified when
* this response is received.
*/
private[http] final case class AjaxRequestInfo(requestVersion:Int,
existingResponse:Box[Box[LiftResponse]],
pendingActors:List[LiftActor],
lastSeen: Long)

/**
* The LiftSession class containg the session state information
*/
Expand Down Expand Up @@ -557,6 +567,16 @@ class LiftSession(private[http] val _contextPath: String, val uniqueId: String,
*/
private var postPageFunctions: Map[String, PostPageFunctions] = Map()

/**
* A list of AJAX requests that may or may not be pending for this
* session. There is up to one entry per RenderVersion.
*/
private var ajaxRequests = scala.collection.mutable.Map[String,AjaxRequestInfo]()

private[http] def withAjaxRequests[T](fn: (scala.collection.mutable.Map[String, AjaxRequestInfo]) => T) = {
ajaxRequests.synchronized { fn(ajaxRequests) }
}

/**
* The synchronization lock for the postPageFunctions
*/
Expand Down Expand Up @@ -850,6 +870,15 @@ class LiftSession(private[http] val _contextPath: String, val uniqueId: String,
}
}

withAjaxRequests { currentAjaxRequests =>
for {
(version, requestInfo) <- currentAjaxRequests
if (now - requestInfo.lastSeen) > LiftRules.unusedFunctionsLifeTime
} {
currentAjaxRequests -= version
}
}

synchronized {
messageCallback.foreach {
case (k, f) =>
Expand Down Expand Up @@ -977,6 +1006,13 @@ class LiftSession(private[http] val _contextPath: String, val uniqueId: String,
} postPageFunctions += (ownerName -> funcInfo.updateLastSeen)
}

withAjaxRequests { currentAjaxRequests =>
currentAjaxRequests.get(ownerName).foreach {
case info: AjaxRequestInfo =>
currentAjaxRequests += (ownerName -> info.copy(lastSeen = time))
}
}

synchronized {
(0 /: messageCallback)((l, v) => l + (v._2.owner match {
case Full(owner) if (owner == ownerName) =>
Expand Down

0 comments on commit 7d89340

Please sign in to comment.