Here's the Lift CometActor code:
// A CometActor that keeps the user updated class LongTime extends CometActor { private var url: Box[String] = Empty private var progress: Int = 0 // a CometActor that has not been displayed for // 2 minutes is destroyed override def lifespan: Box[TimeSpan] = Full(2 minutes) // get messages from the ThingBuilder override def highPriority = { case BuildStatus(p, Empty) => this.progress = p reRender(false) case BuildStatus(_, Full(u)) => url = Full(u) progress = 100 reRender(false) partialUpdate(RedirectTo(u)) } // start the job override def localSetup() { ThingBuilder ! this super.localSetup() } // display the progress or a link to the result def render = url match { case Full(where) => <span>Your job is complete. <a href={where}>Click Me</a></span> case _ => <span>We're working on your job... it's {progress}% complete</span> } }