Checkin start on real-time stuff so we can merge the bob the branch

This commit is contained in:
Joseph Schorr 2014-02-06 13:36:32 -05:00
parent dbed1300ad
commit c2fb1e5d78
2 changed files with 98 additions and 0 deletions

View file

@ -12,6 +12,7 @@ from endpoints.web import web
from endpoints.tags import tags from endpoints.tags import tags
from endpoints.registry import registry from endpoints.registry import registry
from endpoints.webhooks import webhooks from endpoints.webhooks import webhooks
from endpoints.realtime import realtime
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -26,6 +27,7 @@ application.register_blueprint(tags, url_prefix='/v1')
application.register_blueprint(registry, url_prefix='/v1') application.register_blueprint(registry, url_prefix='/v1')
application.register_blueprint(api, url_prefix='/api') application.register_blueprint(api, url_prefix='/api')
application.register_blueprint(webhooks, url_prefix='/webhooks') application.register_blueprint(webhooks, url_prefix='/webhooks')
application.register_blueprint(realtime, url_prefix='/realtime')
# Remove this for prod config # Remove this for prod config
application.debug = True application.debug = True

96
endpoints/realtime.py Normal file
View file

@ -0,0 +1,96 @@
import logging
import redis
from functools import wraps
from flask import request, make_response, Blueprint, abort, Response
from flask.ext.login import current_user, logout_user
from data import model
from app import app
logger = logging.getLogger(__name__)
realtime = Blueprint('realtime', __name__)
def api_login_required(f):
@wraps(f)
def decorated_view(*args, **kwargs):
if not current_user.is_authenticated():
abort(401)
if (current_user and current_user.db_user() and
current_user.db_user().organization):
abort(401)
if (current_user and current_user.db_user() and
current_user.db_user().robot):
abort(401)
return f(*args, **kwargs)
return decorated_view
# Based off of the SSE flask snippet here: http://flask.pocoo.org/snippets/116/
class ServerSentEvent(object):
def __init__(self, data):
self.data = data
self.event = None
self.id = None
self.desc_map = {
self.data : "data",
self.event : "event",
self.id : "id"
}
def encode(self):
if not self.data:
return ""
lines = ["%s: %s" % (v, k)
for k, v in self.desc_map.iteritems() if k]
return "%s\n\n" % "\n".join(lines)
# The current subscriptions
subscriptions = []
@realtime.route("/")
def index():
debug_template = """
<html>
<head>
</head>
<body>
<h1>Server sent events</h1>
<div id="event"></div>
<script type="text/javascript">
var eventOutputContainer = document.getElementById("event");
var evtSrc = new EventSource("/realtime/subscribe");
evtSrc.onmessage = function(e) {
console.log(e.data);
eventOutputContainer.innerHTML = e.data;
};
</script>
</body>
</html>
"""
return(debug_template)
@realtime.route("/subscribe")
@api_login_required
def subscribe():
def gen():
q = Queue()
subscriptions.append(q)
try:
while True:
result = q.get()
ev = ServerSentEvent(str(result))
yield ev.encode()
except GeneratorExit:
subscriptions.remove(q)
return Response(gen(), mimetype="text/event-stream")