class StreamTestCase(AsyncHTTPTestCase): def get_app(self): return Application([('/',HelloHandler)]) def test_read(self): s = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) s.connect(("localhost",self.get_http_port())) self.stream = Stream(s,io_loop=self.io_loop) self.stream.write(b"GET / HTTP/1.0\r\n\r\n") self.stream.on("data",self.on_data1) self.wait() def on_data1(self,data): self.assertEquals(data.split("\r\n\r\n")[-1],"Hello") self.stop()
class RedisClient(EventEmitter): def __init__(self,*args,**options): self.host = "127.0.0.1" if len(args) < 2 else args[1] self.port = 6379 if len(args) < 1 else args[0] sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) self.options = Jso(options) self.stream = Stream(sock,io_loop=self.options.io_loop) self.stream.connect((self.host,self.port)) self.connected = False self.ready = False self.send_anyway = True self.connections = 0 self.attempts = 1 self.command_queue = collections.deque() self.offline_queue = collections.deque() self.commands_sent = 0 self.retry_delay = .25 self.retry_timer = None self.emitted_end = False self.current_retry_delay = self.retry_delay self.retry_backoff = 1.7 self.subscriptions = False self.monitoring = False self.closing = False self.server_info = Jso() self.auth_pass = None self.encoding = self.options.encoding or 'utf-8' self.encoding_error = self.options.encoding_error or 'strict' self.reply_parser = Parser() self.reply_parser.on("reply_error",self.return_error) self.reply_parser.on("reply",self.return_reply) self.reply_parser.on("error",self.return_error_unrecoverable) self.stream.on("connect",self.on_connect) self.stream.on("data",self.on_data) #TODO: create error event #self.stream.on("error",self.on_error) self.stream.on("close",functools.partial(self.connection_gone,"close")) self.stream.on("end",functools.partial(self.connection_gone,"end")) #### Parser Callbacks #### def return_error_unrecoverable(self,err): self.emit("error",ReplyParserError(str(err))) def return_error(self,err): command_obj = self.command_queue.popleft() if not self.subscriptions and len(self.command_queue) == 0: self.emit("idle") if command_obj and operator.isCallable(command_obj.callback): command_obj.call_callback(None,err) else: logging.debug("tornado-redis: no callback to send error: %s" % str(err)) #IOLoop.instance().add_callback(functools.partial(self.raise_error,err)) def return_reply(self,reply): command_obj = self.command_queue.popleft() if len(self.command_queue) > 0 else None if not self.subscriptions and len(self.command_queue) == 0: self.emit("idle") if command_obj and not command_obj.sub_command: if operator.isCallable(command_obj.callback): if reply and command_obj.command.lower() == 'hgetall': i = 0 obj = Jso() while i < len(reply): key = str(reply[i]) val = reply[i+1] obj[key] = val reply = obj command_obj.call_callback(reply,None) else: logging.debug("no callback for reply: %s" % reply) elif self.subscriptions or (command_obj and command_obj.sub_command): if isinstance(reply,list): if reply[0] in ["subscribe","unsubscribe","psubscribe"] and reply[2] == 0: self.subscriptions = False logging.debug("All subscriptions removed, exiting pub/sub mode") if reply[0] not in ["message","pmessage","subscribe","unsubscribe","psubscribe"]: raise TypeError("subscriptions are active but unknow reply type %s" % reply[0]) try: self.emit(*reply) except Exception: logging.error("Uncaught exceptions in subscriptions.", exc_info=True) elif not self.closing: raise ValueError("subscriptions are active but got an invalid reply: %s" % str(reply)) elif self.monitoring: l = reply.index(" ") timestamp = replice[:l] finds = re.finditer('[^"]+',reply[l:]) args = [] for find in finds: args.append(find.replace('"','')) self.emit("monitor",timestamp,args) else: raise ValueError("tornado-redis command queue state error. If you can reproduce this, please report it") #### Stream Callbacks #### def on_connect(self): logging.debug("Stream connected %s:%d fd %s" % (self.host,self.port,self.stream.socket.fileno())) self.connected = True self.ready = False self.attempts = 0 self.connections += 1 self.current_retry_delay = self.retry_timer #TODO: implement stream retry delay if self.auth_pass: self.do_auth() else: self.emit("connect") if self.options.no_ready_check: self.ready = True self.send_offline_queue() else: self.ready_check() def on_data(self,data): logging.debug("net read %s:%d fd %s %s" % (self.host,self.port,self.stream.socket.fileno(),str(data))) try: self.reply_parser.execute(data) except Exception,e: self.emit("error",e)