I recently started playing with Lift and I have been very impressed so
far. However, I am having a problem that I cannot seem to figure out.
As a toy project, I am making a very simple collaborative text editor
using differential synchronization (
http://neil.fraser.name/writing/
sync/ if you are curious). I wanted to use comet so I am having the
server push the text of the shared document to all the clients (I saw
in Simply Lift that Lift does some cool stuff to only send the changes
to the client). When I open up around 6 editors, however, lift freezes
but there is no stack trace in the output. I am sending a lot of ajax
requests (2/sec per client editor), but changing the frequency of
these updates did not affect how many documents I could open. Further,
when I turned off the comet, I was able to open many, many documents
sending 2 req/s and lift did not have a problem handling them. Since I
am brand new to lift, I figure I am doing something wrong in my comet
code, so I have included it below:
// EditorServer.scala
import name.fraser.neil.plaintext._
import diff_match_patch._
import java.util.List
import java.util.LinkedList
import net.liftweb._
import http._
import actor._
object EditorServer extends LiftActor with ListenerManager {
private var text: String = ""
private val dmp = new diff_match_patch()
private val lock = new Object();
def createUpdate = text
override def lowPriority = {
case s: String => {
val patches: List[Patch] = dmp.patch_fromText(s)
lock.synchronized {
text =
dmp.patch_apply(patches.asInstanceOf[LinkedList[Patch]], text)
(0).asInstanceOf[String]
}
updateListeners()
}
}
}
// Editor.scala
package code.comet
import net.liftweb._
import http._
import util._
import Helpers._
import js.JE
import net.liftweb.http.js.JsCmds
import scala.xml.Text
import net.liftweb.http.js.JE.JsRaw
import net.liftweb.http.JsContext
import net.liftweb.common.Empty
import net.liftweb.http.js.JsCmd
class Editor extends CometActor with CometListener {
private var shadow: String = ""
def registerWith = EditorServer
override def lowPriority = {
case v: String =>
shadow = v
reRender()
}
def render = "#serverText *" #> shadow
}
// end code
Essentially, client diffs are sent as ajax requests (in a separate
snippet) and are passed to the EditorServer where they are applied to
the text. The EditorServer then sends the document to all the Editors
who update the value of the document in the client by changing the
child of the textarea with id "serverText". I apologize in advance if
I am doing something blatantly wrong.
Also, I have attached my sbt.bat for good measure:
set SCRIPT_DIR=%~dp0
java -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=512m -Xmx712M -
Xss2M -jar "%SCRIPT_DIR%\sbt-launcher.jar" %*
Using Jetty 6, Lift 2.4, 64bit jvm
Thanks a lot!