def stats(client_reader, client_writer): try: log.info('Clients: %s', SERVER.active_count) client_writer.write(("HTTP/1.0 200 OK\n" "Cache: nocache\n\n").encode()) client_writer.write(('data: %s\n\n' % SERVER.active_count).encode()) yield trololio.From(client_writer.drain()) except trololio.ConnectionResetError as err: log.info(err) finally: client_writer.close() return
def handle_client(client_reader, client_writer): data = None while True: # give client a chance to respond, timeout after 10 seconds line = yield trololio.From( trololio.wait_for(client_reader.readline(), timeout=10.0)) if not line.decode().strip(): break line = line.decode().rstrip() if data is None: data = line if data is None: log.warning("Expected ticket uid, received None") return data = data.decode().rstrip().split() log.info("Received %s", data) if not data: log.warning("No URL provided: %s" % data) return if '/' not in data[1]: log.warning("Invalid URL provided: %s" % data[1]) return url = urlparse(data[1]) try: obj = get_obj_from_path(url.path) except PagureException as err: log.warning(err.message) return origin = pagure.config.config.get('APP_URL') if origin.endswith('/'): origin = origin[:-1] client_writer.write( ("HTTP/1.0 200 OK\n" "Content-Type: text/event-stream\n" "Cache: nocache\n" "Connection: keep-alive\n" "Access-Control-Allow-Origin: %s\n\n" % origin).encode()) conn = redis.Redis(connection_pool=POOL) subscriber = conn.pubsub(ignore_subscribe_messages=True) try: subscriber.subscribe('pagure.%s' % obj.uid) # Inside a while loop, wait for incoming events. oncall = 0 while True: msg = subscriber.get_message() if msg is None: # Send a ping to see if the client is still alive if oncall >= 5: # Only send a ping once every 5 seconds client_writer.write(('event: ping\n\n').encode()) oncall = 0 oncall += 1 yield trololio.From(client_writer.drain()) yield trololio.From(trololio.sleep(1)) else: log.info("Sending %s", msg['data']) client_writer.write(('data: %s\n\n' % msg['data']).encode()) yield trololio.From(client_writer.drain()) except OSError: log.info("Client closed connection") except trololio.ConnectionResetError as err: log.exception("ERROR: ConnectionResetError in handle_client") except Exception as err: log.exception("ERROR: Exception in handle_client") log.info(type(err)) finally: # Wathever happens, close the connection. log.info("Client left. Goodbye!") subscriber.close() client_writer.close()