def application(env, start_response): # complete the handshake uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) r = redis.StrictRedis(host='redis-gandamu', port=6379, db=0) channel = r.pubsub() channel.subscribe('portfolio') websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: uwsgi.wait_fd_read(websocket_fd, 3) uwsgi.wait_fd_read(redis_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd > -1: if fd == websocket_fd: msg = uwsgi.websocket_recv_nb() if msg: r.publish('portfolio', msg) elif fd == redis_fd: msg = channel.parse_response() # only interested in user messages t = 'message' if sys.version_info[0] > 2: t = b'message' if msg[0] == t: json = msg[2].decode('utf-8') uwsgi.websocket_send("%s" % json) # uwsgi.websocket_send("[%s] %s" % (time.time(), msg)) else: # on timeout call websocket_recv_nb again to manage ping/pong msg = uwsgi.websocket_recv_nb() if msg: r.publish('portfolio', msg)
def serve_handler(self, handler, values): def invoke_handler(handler, sock): try: handler(sock, **values) finally: sock.close() th = Thread(target=invoke_handler, args=(handler, self,)) th.setDaemon(True) th.start() try: fd = uwsgi.connection_fd() while not self.evt_close.is_set(): uwsgi.wait_fd_read(fd, 0.3) uwsgi.suspend() _fd = uwsgi.ready_fd() msg = uwsgi.websocket.recv_nb() if msg: self.q_recv.put(msg) try: msg = self.q.get(True, 0.1) if msg: uwsgi.websocket_send(msg) except Empty: pass finally: self.close() th.join() return []
def application(env, start_response): counter = 0 start_response( '200 OK', [ ('Content-Type','text/html') ]) start_time = time.time() for i in range(1,100000): uwsgi.suspend() # print every 100 if i % 100 == 0: yield "<h1>%d</h1>\n" % i counter = counter + i yield "<h1>%d cycles after %d</h1>\n" % (counter, time.time() - start_time)
def application(env, start_response): counter = 0 start_response('200 OK', [('Content-Type', 'text/html')]) start_time = time.time() for i in range(1, 100000): uwsgi.suspend() # print every 100 if i % 100 == 0: yield "<h1>%d</h1>\n" % i counter = counter + i yield "<h1>%d cycles after %d</h1>\n" % (counter, time.time() - start_time)
def application(e, sr): sr('200 OK', [('Content-Type','text/plain')]) # call suspend 10 times and yield some value for i in range(0,10): print i uwsgi.suspend() yield str(i) # connect to a memcached server fd = uwsgi.async_connect('127.0.0.1:11211') try: # start waiting for socket availability (4 seconds max) uwsgi.wait_fd_write(fd, 4) # suspend execution 'til event uwsgi.suspend() uwsgi.send(fd, "get /foobar\r\n") # now wait for memcached response uwsgi.wait_fd_read(fd, 4) uwsgi.suspend() # read the response data = uwsgi.recv(fd, 4096) # return to the client yield data finally: uwsgi.close(fd) print "sleeping for 3 seconds..." uwsgi.async_sleep(3) uwsgi.suspend() yield "done"
def application(e, sr): sr('200 OK', [('Content-Type', 'text/plain')]) # call suspend 10 times and yield some value for i in range(0, 10): print(i) uwsgi.suspend() yield str(i) # connect to a memcached server fd = uwsgi.async_connect('127.0.0.1:11211') try: # start waiting for socket availability (4 seconds max) uwsgi.wait_fd_write(fd, 4) # suspend execution 'til event uwsgi.suspend() uwsgi.send(fd, "get /foobar\r\n") # now wait for memcached response uwsgi.wait_fd_read(fd, 4) uwsgi.suspend() # read the response data = uwsgi.recv(fd, 4096) # return to the client yield data finally: uwsgi.close(fd) print("sleeping for 3 seconds...") uwsgi.async_sleep(3) uwsgi.suspend() yield "done"
def process_response(self, request, response): # clusters - a list with varnish clusters to refresh clusters = VclRefreshState.get_refresh(request.id) if 'error_message' in request.session: del request.session['error_message'] if len(clusters) > 0: start = time.perf_counter() try: result = load_vcl_task.delay( timezone.now(), [cluster.id for cluster in clusters]) if 'tastypie' in str(type( response)) and 'respond-async' in request.META.get( 'HTTP_PREFER', ''): response.status_code = 202 response['Location'] = '/api/v0.1/task/{}/'.format( result.id) else: if settings.ENABLE_UWSGI_SWITCH_CONTEXT: try: import uwsgi while not result.ready(): uwsgi.async_sleep(1) uwsgi.suspend() except: pass result.get() if isinstance(result.result, Exception): raise result.result except SoftTimeLimitExceeded: logging.error( "Time for finish the task has been reached: The task with id {} will be killed." .format(result.id)) except Exception as e: logging.info("Error while reloading cluster: %s (%s)" % (e, type(response))) if 'tastypie' in str(type(response)): return HttpApplicationError( "%s: %s" % (e.__class__.__name__, str(e)[:400])) request.session['error_message'] = "%s: %s" % ( e.__class__.__name__, unescape_exception(e)) logging.info("cluster reload time: %f" % (time.perf_counter() - start)) return response
def wait(self): # Remove context as we are switching between green thread # (and therefore websocket request) self.ws._pop_context() uwsgi.wait_fd_read(self.websocket_fd, 3) uwsgi.wait_fd_read(self.db_fd, 5) uwsgi.suspend() # Restoring request context for all other operations self.ws._push_context() fd = uwsgi.ready_fd() if fd == self.websocket_fd: return "websocket" if fd == self.db_fd: return "db" # Try ping / ponging the websocket in case of error return "timeout"
def recv(server, sock): while not sock.evt_open.is_set(): time.sleep(0.05) if hasattr(server, 'on_open'): server.on_open(self) try: fd = uwsgi.connection_fd() while not sock.evt_close.is_set(): uwsgi.wait_fd_read(fd, 1.0) uwsgi.suspend() _fd = uwsgi.ready_fd() msg = uwsgi.websocket_recv_nb() if msg: frame = (1, OP_TEXT, msg) server.on_message(sock, frame) finally: sock.evt_close.set()
def async_wait(conn): # conn can be a connection or a cursor if not hasattr(conn, 'poll'): conn = conn.connection # interesting part: suspend until ready while True: state = conn.poll() if state == psycopg2.extensions.POLL_OK: break elif state == psycopg2.extensions.POLL_READ: uwsgi.wait_fd_read(conn.fileno()) uwsgi.suspend() elif state == psycopg2.extensions.POLL_WRITE: uwsgi.wait_fd_write(conn.fileno()) uwsgi.suspend() else: raise Exception("Unexpected result from poll: %r", state)
def send_request(env, client): uwsgi.send(client, b"GET /intl/it_it/images/logo.gif HTTP/1.0\r\n") # test for suspend/resume uwsgi.suspend() uwsgi.send(client, b"Host: www.google.it\r\n\r\n") while 1: yield uwsgi.wait_fd_read(client, 2) if env['x-wsgiorg.fdevent.timeout']: return buf = uwsgi.recv(client, 4096) if buf: yield buf else: break
def wsSubData_nb(self): """Websocket subscribe redis pubsub nonbolocking. Keepalive websocket connection with client.""" uwsgi.websocket_handshake(self.environ['HTTP_SEC_WEBSOCKET_KEY'], self.environ.get('HTTP_ORIGIN', '')) channel = self.r.pubsub() channel.subscribe(self.channel) channel.parse_response() websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: uwsgi.wait_fd_read(websocket_fd, 3) uwsgi.wait_fd_read(redis_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd > -1: if fd == websocket_fd: uwsgi.websocket_recv_nb() elif fd == redis_fd: wsdata = channel.parse_response()[2] uwsgi.websocket_send(wsdata) else: uwsgi.websocket_recv_nb() time.sleep(1)
def application(e, sr): sr('200 OK', [('Content-Type', 'text/plain')]) # suspend 10 times and yield a value for i in range(1, 10): print i uwsgi.suspend() yield str(i) # connect to a memcached server fd = uwsgi.async_connect('127.0.0.1:11211') try: command = "get /foobar\r\n" remains = len(command) while remains > 0: # start waiting for socket availability (4 seconds max) uwsgi.wait_fd_write(fd, 4) # suspend execution 'til event uwsgi.suspend() pos = len(command) - remains written = uwsgi.send(fd, command[pos:]) remains -= written # now wait for memcached response uwsgi.wait_fd_read(fd, 4) uwsgi.suspend() # read a chunk of data data = uwsgi.recv(fd, 4096) # .. and yield it yield data finally: # always ensure sockets are closed uwsgi.close(fd) print "sleeping for 3 seconds..." uwsgi.async_sleep(3) uwsgi.suspend() yield "done"
def application(env, start_response): request = Request(env) try: uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) except OSError as err: logging.info('handshake_failed') else: with cursor_for_request(request) as cursor: db_connection = cursor.connection db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) db_conn_fd = db_connection.fileno() websocket_fd = uwsgi.connection_fd() logging.info('connection established') try: while True: uwsgi.wait_fd_read(websocket_fd) uwsgi.wait_fd_read(db_conn_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd == websocket_fd: cmd_json = uwsgi.websocket_recv_nb() if cmd_json: cmd = json.loads(cmd_json.decode('utf-8')) if cmd: try: if cmd['method'] != 'ping': logging.info('command received: %s' % cmd['method']) if cmd['method'] == 'request': request_method(cmd, cursor) elif cmd['method'] == 'attach': attach_method(cmd, cursor, db_connection, env) elif cmd['method'] == 'detach': detach_method(cmd, cursor, db_connection, env) except Warning as err: logging.error(str(err)) # uwsgi.websocket_send(json.dumps({ # "method": "log", # "args": { # "level": "warning", # "message": err.diag.message_primary # } # })) elif fd == db_conn_fd: handle_db_notifications(db_connection) else: logging.info('timeout reached') # This is never reached # handle timeout of above wait_fd_read for ping/pong uwsgi.websocket_recv_nb() except (OSError, IOError) as err: logging.info('connection closed (role: %s)' % env['DB_USER']) return []
def application(env, sr): ws_scheme = 'ws' if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https': ws_scheme = 'wss' if env['PATH_INFO'] == '/': sr('200 OK', [('Content-Type','text/html')]) output = """ <!doctype html> <html> <head> <meta charset="utf-8"> <script language="Javascript"> var s = new WebSocket("%s://%s/foobar/"); s.onopen = function() { console.log("connected !!!"); s.send("hello"); }; s.onmessage = function(e) { var bb = document.getElementById('blackboard') var html = bb.innerHTML; bb.innerHTML = html + '<br/>' + e.data; }; s.onerror = function(e) { console.log(e); } s.onclose = function(e) { console.log("connection closed"); } function invia() { var value = document.getElementById('testo').value; s.send(value); } </script> </head> <body> <h1>WebSocket</h1> <input type="text" id="testo"/> <input type="button" value="invia" onClick="invia();"/> <div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto"> </div> </body> </html> """ % (ws_scheme, env['HTTP_HOST']) return output.encode() elif env['PATH_INFO'] == '/favicon.ico': return "" elif env['PATH_INFO'] == '/foobar/': uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) print("websockets...") msg_srv_fd = uwsgi.async_connect("127.0.0.1:8888") websocket_fd = uwsgi.connection_fd() while True: uwsgi.wait_fd_read(websocket_fd, 3) uwsgi.wait_fd_read(msg_srv_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd > -1: if fd == websocket_fd: msg = uwsgi.websocket_recv_nb() print("got message over ws: {}".format(msg)) if msg: uwsgi.send(msg_srv_fd, msg) elif fd == msg_srv_fd: msg = uwsgi.recv(msg_srv_fd) print("got message over msg_srv: {}".format(msg)) uwsgi.websocket_send("[%s] %s" % (time.time(), msg.decode())) else: # on timeout call websocket_recv_nb again to manage ping/pong msg = uwsgi.websocket_recv_nb() print("ws ping/pong") if msg: print("got message over ws: {}".format(msg)) uwsgi.send(msg_srv_fd, msg)
v = ffi.string(uo.value) if k in uwsgi.opt: if type(uwsgi.opt[k]) is list: uwsgi.opt[k].append(v) else: uwsgi.opt[k] = [uwsgi.opt[k], v] else: uwsgi.opt[k] = v def uwsgi_pypy_current_wsgi_req(): wsgi_req = lib.uwsgi.current_wsgi_req() if wsgi_req == ffi.NULL: raise Exception("unable to get current wsgi_request, check your setup !!!") return wsgi_req """ uwsgi.suspend() """ def uwsgi_pypy_suspend(): wsgi_req = uwsgi_pypy_current_wsgi_req() if lib.uwsgi.schedule_to_main: lib.uwsgi.schedule_to_main(wsgi_req); uwsgi.suspend = uwsgi_pypy_suspend """ uwsgi.workers() """ def uwsgi_pypy_workers(): workers = [] for i in range(1, lib.uwsgi.numproc+1): worker = {}
def application(env, sr): ws_scheme = 'ws' if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https': ws_scheme = 'wss' if env['PATH_INFO'] == '/': sr('200 OK', [('Content-Type', 'text/html')]) output = """ <html> <head> <script language="Javascript"> var s = new WebSocket("%s://%s/foobar/"); s.onopen = function() { alert("connected !!!"); s.send("ciao"); }; s.onmessage = function(e) { var bb = document.getElementById('blackboard') var html = bb.innerHTML; bb.innerHTML = html + '<br/>' + e.data; }; s.onerror = function(e) { alert(e); } s.onclose = function(e) { alert("connection closed"); } function invia() { var value = document.getElementById('testo').value; s.send(value); } </script> </head> <body> <h1>WebSocket</h1> <input type="text" id="testo"/> <input type="button" value="invia" onClick="invia();"/> <div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto"> </div> </body> </html> """ % (ws_scheme, env['HTTP_HOST']) if sys.version_info[0] > 2: return output.encode('latin1') return output elif env['PATH_INFO'] == '/favicon.ico': return "" elif env['PATH_INFO'] == '/foobar/': uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) print("websockets...") r = redis.StrictRedis(host='localhost', port=6379, db=0) channel = r.pubsub() channel.subscribe('foobar') websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: uwsgi.wait_fd_read(websocket_fd, 3) uwsgi.wait_fd_read(redis_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd > -1: if fd == websocket_fd: msg = uwsgi.websocket_recv_nb() if msg: r.publish('foobar', msg) elif fd == redis_fd: msg = channel.parse_response() print(msg) # only interested in user messages t = 'message' if sys.version_info[0] > 2: t = b'message' if msg[0] == t: uwsgi.websocket_send("[%s] %s" % (time.time(), msg)) else: # on timeout call websocket_recv_nb again to manage ping/pong msg = uwsgi.websocket_recv_nb() if msg: r.publish('foobar', msg)
def application(env, start_response): request = Request(env) try: uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) except OSError as err: logging.info('handshake_failed') else: with cursor_for_request(request) as cursor: db_connection = cursor.connection db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) db_conn_fd = db_connection.fileno() websocket_fd = uwsgi.connection_fd() logging.info('connection established') try: while True: uwsgi.wait_fd_read(websocket_fd) uwsgi.wait_fd_read(db_conn_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd == websocket_fd: cmd_json = uwsgi.websocket_recv_nb() if cmd_json: cmd = json.loads(cmd_json.decode('utf-8')) if cmd: try: if cmd['method'] != 'ping': logging.info('command received: %s' % cmd['method']) if cmd['method'] == 'request': logging.info( 'websocket endpoint request: %s, %s, %s, %s' % ( cmd['verb'], # HTTP method - GET, POST, PATCH, DELETE cmd['uri'], # selector - '/relation/widget/dependency_js' ImmutableMultiDict( json.loads(cmd['query']) ), # query string arguments - including event.session id json.dumps( cmd['data']) # post data )) cursor.execute( 'select status, message, response, mimetype from endpoint.request2(%s, %s, %s::json, %s::json);', ( cmd['verb'], # HTTP method - GET, POST, PATCH, DELETE cmd['uri'], # selector - '/relation/widget/dependency_js' json.dumps( ImmutableMultiDict( json.loads( cmd['query']) ).to_dict(flat=False) ), # query string arguments - including event.session id json.dumps( cmd['data']) # post data )) result = cursor.fetchone() uwsgi.websocket_send('''{ "method": "response", "request_id": "%s", "data": %s }''' % (cmd['request_id'], result.response)) elif cmd['method'] == 'attach': session_id = cmd['session_id'] if session_id is not None: cursor.execute( 'select event.session_attach(%s);', (session_id, )) logging.info( 'session attached: %s (role: %s)' % (session_id, env['DB_USER'])) handle_db_notifications( db_connection) uwsgi.websocket_send('''{ "method": "response", "request_id": "%s", "data": "true" }''' % (cmd['request_id'], )) elif cmd['method'] == 'detach': session_id = cmd['session_id'] if session_id is not None: cursor.execute( 'select event.session_detach(%s);', (session_id, )) logging.info( 'session detached: %s (role: %s)' % (session_id, env['DB_USER'])) uwsgi.websocket_send('''{ "method": "response", "request_id": "%s", "data": "true" }''' % (cmd['request_id'], )) #uwsgi.websocket_send('''{ # "method": "response", # "request_id": "%s", # "data": %s #}''' % (cmd['request_id'], result.response)) except Warning as err: logging.error(str(err)) # uwsgi.websocket_send(json.dumps({ # "method": "log", # "args": { # "level": "warning", # "message": err.diag.message_primary # } # })) elif fd == db_conn_fd: handle_db_notifications(db_connection) else: logging.info( 'timeout reached') # This is never reached # handle timeout of above wait_fd_read for ping/pong uwsgi.websocket_recv_nb() except (OSError, IOError) as err: logging.info('connection closed (role: %s)' % env['DB_USER']) return []
def get(self): def handle_request(r, msg): """Handle request for more messages received from websocket.""" request = json.loads(msg) first = int(request["first_id"]) last = int(request["last_id"]) # Don't fetch more than 50 messages at once: if (last > 0 and (last - 50 > first)) or (last < 0): first = last - 50 pickled_messages = r.lrange(REDIS_MESSAGES_KEY, first, last) messages = [] for pickled_message in pickled_messages: message = pickle.loads(pickled_message) messages.append(message) uwsgi.websocket_send(encode_messages(messages)) # The first thing we need to do is take what seems like a normal HTTP # request and upgrade it to be a websocket request: uwsgi.websocket_handshake(os.getenv('HTTP_SEC_WEBSOCKET_KEY', ''), os.getenv('HTTP_ORIGIN', '')) # Open a connection to the Redis server, and ask to be notified of any # messages on the channel REDIS_CHANNEL: r = redis.StrictRedis(host='localhost', port=6379, db=0) channel = r.pubsub() channel.subscribe(REDIS_CHANNEL) # We then want to go to sleep and wait for messages either from Redis, # or from this websocket. So we need to know their file descriptors: websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: # Setup both FDs with epoll so we can wait for messages. Wake up # every 3 seconds to ensure that ping messages get exchanged on the # websocket connection to keep it alive: uwsgi.wait_fd_read(websocket_fd, 3) uwsgi.wait_fd_read(redis_fd) # Put thread to sleep until message arrives or timeout. Note that # if you do not use a suspend engine (such as ugreen) this will just # immediately return without suspending, nothing will work, and you # will get horribly confused. uwsgi.suspend() fd = uwsgi.ready_fd() if fd > -1: if fd == websocket_fd: try: msg = uwsgi.websocket_recv_nb() if msg: handle_request(r, msg) except IOError, e: # Websocket has failed in some way (such as a browser # reload), just close it and let the app re-open if it # is still there to do so: return elif fd == redis_fd: # Got a message from Redis, pass it on to the browser # through the websocket. msg = channel.parse_response() # Redis sends both control messages and user messages # through this fd. Send only user-generated messages to all # clients: if msg[0] == b'message': uwsgi.websocket_send(msg[2]) else: # We got a timeout. Call websocket_recv_nb again to manage # ping/pong: try: msg = uwsgi.websocket_recv_nb() if msg: handle_request(r, msg) except IOError, e: # Websocket has failed in some way (such as a browser # reload), just close it and let the app re-open if it is # still there to do so: return
def application(env, start_response): request = Request(env) try: uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) except OSError as err: logging.info('handshake_failed') else: with cursor_for_request(request) as cursor: db_connection = cursor.connection db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) db_conn_fd = db_connection.fileno() websocket_fd = uwsgi.connection_fd() logging.info('connection established') try: while True: uwsgi.wait_fd_read(websocket_fd) uwsgi.wait_fd_read(db_conn_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd == websocket_fd: cmd_json = uwsgi.websocket_recv_nb() if cmd_json: cmd = json.loads(cmd_json.decode('utf-8')) if cmd: try: if cmd['method'] != 'ping': logging.info('command received: %s' % cmd['method']) if cmd['method'] == 'request': request_method(cmd, cursor) elif cmd['method'] == 'attach': attach_method(cmd, cursor, db_connection, env) elif cmd['method'] == 'detach': detach_method(cmd, cursor, db_connection, env) except Warning as err: logging.error(str(err)) # uwsgi.websocket_send(json.dumps({ # "method": "log", # "args": { # "level": "warning", # "message": err.diag.message_primary # } # })) elif fd == db_conn_fd: handle_db_notifications(db_connection) else: logging.info( 'timeout reached') # This is never reached # handle timeout of above wait_fd_read for ping/pong uwsgi.websocket_recv_nb() except (OSError, IOError) as err: logging.info('connection closed (role: %s)' % env['DB_USER']) return []
def application(env, start_response): request = Request(env) try: uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) except OSError as err: logging.info('handshake_failed') else: with cursor_for_request(request) as cursor: db_connection = cursor.connection db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) session_id = get_session_id(request, cursor) logging.info('event/table/session/row/%s:connected (role: %s)' % (session_id, env['DB_USER'])) db_conn_fd = db_connection.fileno() websocket_fd = uwsgi.connection_fd() cursor.execute('listen "event/table/session/rows/%i"' % session_id) try: while True: uwsgi.wait_fd_read(websocket_fd) uwsgi.wait_fd_read(db_conn_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd == websocket_fd: cmd_json = uwsgi.websocket_recv_nb() if cmd_json: cmd = json.loads(cmd_json.decode('utf-8')) if cmd: try: if cmd['method'] == 'subscribe': selector, type = cmd['args'][ 'selector'].rsplit(':', 1) cursor.execute( "select event.subscribe_session(%s, %s, %s);", (session_id, selector, type)) elif cmd['method'] == 'unsubscribe': selector, type = cmd['args'][ 'selector'].rsplit(':', 1) cursor.execute( "select event.unsubscribe_session(%s, %s, %s);", (session_id, selector, type)) except Warning as err: logging.error(str(err)) uwsgi.websocket_send( json.dumps({ "method": "log", "args": { "level": "warning", "message": err.diag.message_primary } })) elif fd == db_conn_fd: db_connection.poll() if db_connection.notifies: del db_connection.notifies[:] cursor.execute( ''' select * from event.session_queued_events_json(%s) ''', (session_id, )) qe_ids = [] logging.info( 'event/table/session/row/%s:flushing_queue (role: %s)' % (session_id, env['DB_USER'])) for row in cursor: uwsgi.websocket_send(json.dumps( row.event_json)) logging.info( 'event/table/session/row/%s:sent_json (role: %s)' % (session_id, env['DB_USER'])) qe_ids.append(row.queued_event_id) cursor.execute( ''' delete from event.queued_event qe where qe.id = any(%s) ''', (qe_ids, )) else: # handle timeout of above wait_fd_read for ping/pong uwsgi.websocket_recv_nb() except OSError as err: logging.info( 'event/table/session/row/%s:disconnected (role: %s)' % (session_id, env['DB_USER'])) return []
def application(env, start_response): request = Request(env) try: uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) except OSError as err: logging.info('handshake_failed') else: with cursor_for_request(request) as cursor: db_connection = cursor.connection db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) session_id = get_session_id(request, cursor) logging.info('event/table/session/row/%s:connected (role: %s)' % (session_id, env['DB_USER'])) db_conn_fd = db_connection.fileno() websocket_fd = uwsgi.connection_fd() cursor.execute('listen "event/table/session/rows/%i"' % session_id) try: while True: uwsgi.wait_fd_read(websocket_fd) uwsgi.wait_fd_read(db_conn_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd == websocket_fd: cmd_json = uwsgi.websocket_recv_nb() if cmd_json: cmd = json.loads(cmd_json.decode('utf-8')) if cmd: try: if cmd['method'] == 'subscribe': selector, type = cmd['args']['selector'].rsplit(':', 1) cursor.execute("select event.subscribe_session(%s, %s, %s);", (session_id, selector, type)) elif cmd['method'] == 'unsubscribe': selector, type = cmd['args']['selector'].rsplit(':', 1) cursor.execute("select event.unsubscribe_session(%s, %s, %s);", (session_id, selector, type)) except Warning as err: logging.error(str(err)) uwsgi.websocket_send(json.dumps({ "method": "log", "args": { "level": "warning", "message": err.diag.message_primary } })) elif fd == db_conn_fd: db_connection.poll() if db_connection.notifies: del db_connection.notifies[:] cursor.execute(''' select * from event.session_queued_events_json(%s) ''', (session_id,)) qe_ids = [] logging.info('event/table/session/row/%s:flushing_queue (role: %s)' % (session_id, env['DB_USER'])) for row in cursor: uwsgi.websocket_send(json.dumps(row.event_json)) logging.info('event/table/session/row/%s:sent_json (role: %s)' % (session_id, env['DB_USER'])) qe_ids.append(row.queued_event_id) cursor.execute(''' delete from event.queued_event qe where qe.id = any(%s) ''', (qe_ids,)) else: # handle timeout of above wait_fd_read for ping/pong uwsgi.websocket_recv_nb() except OSError as err: logging.info('event/table/session/row/%s:disconnected (role: %s)' % (session_id, env['DB_USER'])) return []
def recv(self, bufsize): if not self.closed: uwsgi.wait_fd_read(self.fileno(), -1) uwsgi.suspend() if not self.closed: return uwsgi.recv(self.fileno(), bufsize)
def raw_recv(self): import uwsgi uwsgi.wait_fd_read(self.fd) uwsgi.suspend() return uwsgi.recv(self.fd, self.bufsize)