/
MyLiftActor.scala
170 lines (134 loc) · 4.77 KB
/
MyLiftActor.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package com.fmpwizard.code
package comet
import scala.xml.{NodeSeq, Text, Elem}
import net.liftweb._
import util._
import actor._
import http._
import common.{Box, Full,Logger}
import mapper.{OrderBy, Descending, SelectableField}
import http.SHtml._
import http.S._
import http.js.JsCmds.{SetHtml, SetValueAndFocus, Replace}
import http.js.jquery.JqJE._
import net.liftweb.http.js.JE.Str
import Helpers._
/**
* This is the message we pass around to
* register each named comet actor with a dispatcher that
* only updates the specific version it monitors
*/
case class registerCometActor(actor: CometActor, version: String)
/**
* The message we pass around to update the UI
* once we are done with our long running process
*/
case class DoneMessage(CometActorName: String, City: String, State: String)
class Myliftactor extends CometActor with Logger {
override def defaultPrefix = Full("comet")
// time out the comet actor if it hasn't been on a page for 2 minutes
override def lifespan = Full(120 seconds)
/**
* On page load, this method does a full page render
*/
def render= {
"#result *" #> "5 seconds after you submit, you will see a new message here."
}
/**
* We can get two kinds of messages
* 1- A DoneMessage, which has info about the long
* running process we just finished.
* A LiftActor sends this message
*
* 2- A string which is the version the comet actor is displaying info about
* On page load we get this message
*
*/
override def lowPriority: PartialFunction[Any,Unit] = {
case DoneMessage(cometActorName, city, state) => {
info("Comet Actor %s will do a partial update".format(this))
/**
* each td in the html grid has an id that is
* [0-9] + browser name
* I use this to uniquely identify which cell to update
*
*/
partialUpdate(
SetHtml("result", <span>I finished processing your form.<br />
You submitted <b>{state}, {city}</b></span>)
)
}
case Full(name: String)=> {
info("[URL]: CometActor monitoring session: %s".format(name))
/**
* We get the DispatcherActor that sends message to all the
* CometActors that are displaying a specific version number.
* And we register ourselves with the dispatcher
*/
//name map{n => MyListeners.listenerFor(n) ! registerCometActor(this, n) }
MyListeners.listenerFor(name) ! registerCometActor(this, name)
//MyListeners.listenerFor(name)
info("Registering comet actor: %s".format(this))
reRender()
}
case _ => info("Not sure how we got here.")
}
}
/**
* This class keeps a list of comet actors that need to update the UI
* if we get new data through the rest api
*/
class DispatcherActor(name: String) extends LiftActor with Logger{
//info("DispatcherActor got version: %s".format(name))
private var doneMessage= DoneMessage("", "Asheville", "North Carolina")
private var cometActorsToUpdate: List[CometActor]= List()
def createUpdate = doneMessage
override def messageHandler = {
/**
* if we do not have this actor in the list, add it (register it)
*/
case registerCometActor(actor, name) =>
if(cometActorsToUpdate.contains(actor) == false){
info("We are adding actor: %s to the list".format(actor))
cometActorsToUpdate= actor :: cometActorsToUpdate
} else {
info("The list so far is %s".format(cometActorsToUpdate))
}
/**
* Go through the the list of actors and send them a cellToUpdate message
*/
case DoneMessage(name, city, state) => {
doneMessage = DoneMessage(name, city, state)
info("We will update these comet actors: %s showing name: %s".format(
cometActorsToUpdate, name))
cometActorsToUpdate.foreach(_ ! doneMessage)
}
case _ => "Bye"
}
}
/**
* Keep a map of versions -> dispatchers, if no dispatcher is found, create one
* comet actors get the ref to their dispatcher using this object,
* so they can register themselves and the rest
* api gets the dispatcher that is monitoring a specific version
*
*/
object MyListeners extends Logger{
//How about creating a ListenerManager (a separate Actor)
//for each of the items you're going to have:
private var listeners: Map[String, LiftActor] = Map()
def listenerFor(str: String): LiftActor = synchronized {
listeners.get(str) match {
case Some(a) => info("Our map is %s".format(listeners)); a
case None => {
val ret = new DispatcherActor(str)
listeners += str -> ret
info("Our map is %s".format(listeners))
ret
}
}
}
//So, you'll have a separate dispatcher for each of your URL parameters
//and the CometActors can register with them and the REST thing can find
//them to send the messages.
}