Checkin start on real-time stuff so we can merge the bob the branch
This commit is contained in:
parent
dbed1300ad
commit
c2fb1e5d78
2 changed files with 98 additions and 0 deletions
|
@ -12,6 +12,7 @@ from endpoints.web import web
|
|||
from endpoints.tags import tags
|
||||
from endpoints.registry import registry
|
||||
from endpoints.webhooks import webhooks
|
||||
from endpoints.realtime import realtime
|
||||
|
||||
|
||||
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(api, url_prefix='/api')
|
||||
application.register_blueprint(webhooks, url_prefix='/webhooks')
|
||||
application.register_blueprint(realtime, url_prefix='/realtime')
|
||||
|
||||
# Remove this for prod config
|
||||
application.debug = True
|
||||
|
|
96
endpoints/realtime.py
Normal file
96
endpoints/realtime.py
Normal 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")
|
Reference in a new issue