diff --git a/web/webkit/src/main/scala/net/liftweb/builtin/snippet/Comet.scala b/web/webkit/src/main/scala/net/liftweb/builtin/snippet/Comet.scala index 19991138bc..ce7654a346 100644 --- a/web/webkit/src/main/scala/net/liftweb/builtin/snippet/Comet.scala +++ b/web/webkit/src/main/scala/net/liftweb/builtin/snippet/Comet.scala @@ -72,8 +72,12 @@ object Comet extends DispatchSnippet with LazyLoggable { case Full(AnswerRender(response, _, when, _)) => c.buildSpan(when, response.inSpan) - case _ => - throw new CometTimeoutException("type: "+theType+" name: "+name) + case e => + if (c.cometRenderTimeoutHandler().isDefined) { + c.cometRenderTimeoutHandler().open_! + } else { + throw new CometTimeoutException("type: "+theType+" name: "+name) + } }}} openOr { throw new CometNotFoundException("type: "+theType+" name: "+name) } diff --git a/web/webkit/src/main/scala/net/liftweb/http/CometActor.scala b/web/webkit/src/main/scala/net/liftweb/http/CometActor.scala index 200686cdfc..c8fbe56261 100644 --- a/web/webkit/src/main/scala/net/liftweb/http/CometActor.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/CometActor.scala @@ -403,6 +403,38 @@ trait LiftCometActor extends TypedActor[Any, Any] with ForwardableActor[Any, Any */ def cometProcessingTimeout = LiftRules.cometProcessingTimeout + /** + * This is to react to comet-requests timing out. + * When the timeout specified in {@link LiftRules#cometProcessingTimeout} occurs one may override + * this to send a message to the user informing of the timeout. + *

+ * Do NOT manipulate actor-state here. If you want to manipulate state, send the actor a new message. + *

+ * Typical example would be: + *

+   *   override def cometTimeoutHandler(): JsCmd = {
+   *     Alert("Timeout processing comet-request, timeout is: " + cometProcessingTimeout + "ms")
+   *   }
+   * 
+ */ + def cometProcessingTimeoutHandler(): JsCmd = Noop + + /** + * This is to react to comet-actors timing out while initial rendering, calls to render(). + * When the timeout specified in {@link LiftRules#cometRenderTimeout} occurs one may override + * this to customise the output. + *

+ * Do NOT manipulate actor-state here. If you want to manipulate state, send the actor a new message. + *

+ * Typical example would be: + *

+   *   override def renderTimeoutHandler(): Box[NodeSeq] = {
+   *     Full(<div>Comet {this.getClass} timed out, timeout is {cometRenderTimeout}ms</div>)
+   *   }
+   * 
+ */ + def cometRenderTimeoutHandler(): Box[NodeSeq] = Empty + protected def initCometActor(theSession: LiftSession, theType: Box[String], name: Box[String], diff --git a/web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala b/web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala index 576a911db1..833580c99f 100644 --- a/web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala @@ -661,6 +661,7 @@ class LiftSession(private[http] val _contextPath: String, val uniqueId: String, a.!?(a.cometProcessingTimeout, ActionMessageSet(f.map(i => buildFunc(i)), state)) match { case Full(li: List[_]) => li case li: List[_] => li + case Empty => Full(a.cometProcessingTimeoutHandler()) case other => Nil }) case _ => f.map(i => buildFunc(i).apply())