def message_from_topic(topic: PubSub, is_json=False, limit: int = 10): while limit >= 0: msg = topic.get_message() if msg is None: break if msg["type"] != "message": # 可能是刚刚连上 continue if is_json: yield json.loads(msg["data"]) else: yield msg["data"]
class SubWebSocket(tornado.websocket.WebSocketHandler): def open(self, *args, **kwargs): self.pubsub = PubSub(REDIS_CONNECTION_POOL, ignore_subscribe_messages=True) self.client = self.request.connection.context.address print("opened") def assemble_cmd(self, log_path, cmd): kill_cmd = "kill `ps aux|grep logtail.py|grep %s|grep -v grep|awk '{print $2}'`" % ( log_path, ) return "{kill};{tail}".format(kill=kill_cmd, tail=cmd) @gen.coroutine def on_message(self, message): local = get_local_client(io_loop=tornado.ioloop.IOLoop.instance()) hostname, log_path, cmd = message.split("||") cmd = self.assemble_cmd(log_path, cmd) self.channel = settings.LOG_KEY.format(server=hostname.strip(), log_path=log_path.strip()) self.pubsub.subscribe(**{self.channel: self.channel_callback}) local.cmd_async(hostname, "cmd.run", [cmd]) while self.pubsub.subscribed: if not self.pubsub.connection.can_read(timeout=0): yield gen.sleep(0.05) else: self.pubsub.get_message() self.pubsub.close() print 'pubsub closed' def channel_callback(self, message): line = format_line(message["data"]) try: self.write_message(line) except tornado.websocket.WebSocketClosedError: self.pubsub.unsubscribe(self.channel) def on_close(self): self.pubsub.unsubscribe(self.channel) print("closed")
def get_distance(pubsub: PubSub) -> float: pubsub.subscribe("subsystem.sonar.measurement", ignore_subscribe_messages=True) timeout = 0.5 start = time.time() while cycle([True]): if time.time() - start > timeout: logger.error("Unable to get sonar measurement!!") raise NoSonarException("Unable to get sonar measurement") redis_message = pubsub.get_message() if redis_message is not None: pubsub.unsubscribe("subsystem.sonar.measurement") message = json.loads(redis_message['data']) return float(message) sleep(0.01)
def get_phrase(redis_client: Redis, pubsub: PubSub, timeout: int = 0) -> str: start = time() request_id = str(uuid1()) redis_client.publish("subsystem.listener.command", dumps({ "mode": "phrase", "request_id": request_id })) logger.debug(f"Listening for phrase (request_id={request_id})") while cycle([True]): waited_so_far = time() - start if timeout and waited_so_far > timeout: raise ListeningTimeoutException( f"Timed out waiting for phrase after {waited_so_far} seconds") if redis_message := pubsub.get_message(): message = loads(redis_message['data']) if message['request_id'] != request_id: logger.debug(f"ignoring request id #{message['request_id']}") continue logger.debug( f"Received a response to request_id #{message['request_id']}") logger.debug(f"Received phrase was {message['transcription']}") return message['transcription'] sleep(0.01)
def wait(self, pubsub: SyncPubsSub, timeout: int = 30, **kwargs) -> Any: """Wait for pub/sub messages & return posted message.""" now = time.time() timeout = now + timeout while now < timeout: message = pubsub.get_message(ignore_subscribe_messages=True, **kwargs) if message is not None and message["type"] == "message": data = message["data"] return self.parse_types(data) time.sleep(0.01) now = time.time() return None