Created
October 3, 2011 14:44
-
-
Save commandodev/1259246 to your computer and use it in GitHub Desktop.
Stargate example app
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import eventlet | |
from eventlet import wsgi | |
from paste.httpserver import serve | |
from pyramid.config import Configurator | |
from pyramid.response import Response | |
from pyramid.view import view_config | |
from stargate import WebSocketAwareResource, WebSocketView, is_websocket | |
import simplejson as json | |
host = "127.0.0.1" | |
port = 9999 | |
home_html = """\ | |
<html> | |
<head> | |
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script> | |
<script> | |
$(function() { | |
ws = new WebSocket("ws://%(host)s:%(port)s/jobs/1/"); | |
ws.onmessage = function(msg) { | |
$("body").append("<p>" + msg.data + "</p>"); | |
}; | |
STARTED = false; | |
$("#start-stop").click(function(evt) { | |
$.post("/jobs/1/", {state: STARTED ? "stop" : "start"}, function(result) { | |
STARTED = !STARTED; | |
$('#start-stop span').text(STARTED ? "on" : "off"); | |
}); | |
}); | |
}); | |
</script> | |
</head> | |
<body> | |
<h1>Hi</h1> | |
<button id="start-stop">Job 1 <span>off</span></button> | |
</body> | |
</html> | |
""" % dict(host=host, port=port) | |
class JobRoot(object): | |
"""A container for jobs | |
Gets or creates Job objects for certain ids | |
""" | |
def __init__(self): | |
self._jobs = {} | |
def __getitem__(self, item): | |
try: | |
return self._jobs[item] | |
except KeyError: | |
return self.create_job(item) | |
def create_job(self, id): | |
job = Job(id, self) | |
self._jobs[id] = job | |
return job | |
class Job(WebSocketAwareResource): | |
"""This is a permanent object. | |
It's responsible for maintaning a list of connected clients (websockets) | |
and updating them when its state changes | |
""" | |
def __init__(self, id, parent): | |
self.__name__ = id | |
self.__parent__ = parent | |
self.state = "OFF" | |
def control(self, state): | |
"""This function updates the state | |
Its called by the control function (in response to a post) | |
It triggers the sending of self.state to all connected clients. If you | |
connect multiple browsers (or tabs) they will all be updated | |
""" | |
self.state = state | |
self.send(state) | |
class JobView(WebSocketView): | |
"""The view connects pyramid with the resource | |
In this simple example it simply adds the websocket to the Job's listeners. | |
It then goes to sleep *blocking the thread it's in* this is where eventlet | |
comes in. In real live in the while True bit you'd do things like listening | |
for updates and handline messages coming in on the websocket | |
""" | |
def handler(self, websocket): | |
job = self.request.context | |
job.add_listener(websocket) | |
while True: | |
eventlet.sleep(60) | |
def control(job, request): | |
"""Post to this view to set the state | |
this will trigger Job to report the state to connected clients | |
""" | |
state = request.POST.get("state") | |
if state: | |
job.control(state) | |
return dict(id=job.__name__, state=job.state) | |
class Root(dict): | |
"""The root of url traversal | |
/jobs/{id} | |
-> Root['jobs'][id] | |
-> Root/JobRoot/Job | |
See https://pylonsproject.org/projects/pyramid/dev/narr/traversal.html | |
""" | |
def __init__(self): | |
super(Root, self).__init__(jobs=JobRoot()) | |
def home(request): | |
"""Serves up home_html, setting up a simple js demo""" | |
return Response(home_html) | |
root = Root() | |
def root_factory(request): | |
return root | |
if __name__ == '__main__': | |
config = Configurator(root_factory=root_factory) | |
config.add_view(home, context=Root) | |
config.add_view(JobView, context=Job, custom_predicates=[is_websocket]) | |
config.add_view(control, context=Job, renderer="json", xhr=True) | |
#config.add_static_view(name='static', path='/Users/tim2/nyb/python') | |
app = config.make_wsgi_app() | |
listener = eventlet.listen((host, port)) | |
wsgi.server(listener, app) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment