async def start_serving(self): try: while True: packet = await mysql.PacketBytesReader.read_execute_packet( self.stream) conn = await PoolManager.acquire() r = await conn.query(packet.query) except torio.StreamClosedError: logger.warning("client has close with.") self.close() except Exception as e: logger.warning("error with %s", str(e))
async def start_handshake(self): try: logger.info("client %s:%s start handshake.", *self.address) self.status = SessionStatus.HANDSHAKEING auth = Handshake(self.stream) handshake_result = await auth.start() if handshake_result: self.status = SessionStatus.HANDSHAKED self.start() else: await self.close() except Exception as e: logger.warning("error with %s", str(e)) await self.close()
def decode(cls, raw: bytes) -> 'Execute': p = cls() try: p.command = Command(raw[0]) p.length = len(raw) except ValueError: logger.warning("unknown command %s, with packet: %s", byte2int(raw[0]), dump_packet(raw)) raise err.OperationalError("unknown command {}.".format( byte2int(raw[0]))) finally: p.args = raw[1:] if p.command is Command.COM_QUERY: p.query = p.args.decode() return p
async def _ending(self, xid: int, action: A2PCAction) -> A2PCResponse: body = json.dumps({"action": action, "xid": xid}) n = (xid % self.mod) if self.mod > 0 else 0 server = self.services[n] url = "http://{}:{}/transactions".format(server[0], server[1]) req = HTTPRequest(url, "PUT", self.header, body) client = AsyncHTTPClient() try: logger.info("put: {}, param: {}".format(url, body)) response = await client.fetch(req) logger.info("response: {}".format(response.body)) return self._parse_result(response) except Exception as e: logger.warning("Error: %s" % e) raise e
async def start_serving(self): try: i = 0 while True: packet = await mysql.PacketBytesReader.read_execute_packet( self.stream) execute = Execute(packet.length, Command(packet.command), packet.args, packet.query) r = await self.dsession.execute(execute) i += 1 num = int(i < 7) if i > 6: num = 0 logger.info(r[0]) if r is not None: await mysql.ResultWriter.write(r, self.stream, num) except torio.StreamClosedError: logger.warning("client has close with.") await self.close() except Exception as e: traceback.print_exc() logger.warning("error with %s", str(e))
async def start_listing(self): try: while True: packet_header = await self.client.read_bytes(4) bytes_to_read, packet_number = self._parse_header( packet_header) res = await self.client.read_bytes(bytes_to_read) p = mysql.PacketBytesReader(res) if p.is_ok_packet(): await self.stream.write(packet_header + res) elif p.is_eof_packet(): await self.stream.write(packet_header + res) elif p.is_error_packet(): await self.stream.write(packet_header + res) else: r = await mysql.ResultSet.decode(res, self.client) await r.encode(0, 2, self.stream, packet_number) except torio.StreamClosedError: logger.warning("client has close with.") self.close() except Exception as e: logger.warning("error with %s", str(e))
async def _execute_ending(self, r: List[Union[result.Result, A2PCResponse]], node: List[DBTableStrategyBackend], sql: DMLW): lock = r[-1] r = r[:-1] ending_sql = "COMMIT" return_v = None if not isinstance(lock, A2PCResponse): ending_sql = "ROLLBACK" return_v = result.Error( 1000, "{} acquire lock fail: {}".format(str(sql.raw), str(lock))) elif lock.status != 0: logger.warning("{} acquire lock fail: {}".format( str(sql.raw), lock.msg)) ending_sql = "ROLLBACK" return_v = result.Error( 1000, "{} acquire lock fail: {}".format(str(sql.raw), lock.msg)) if any([isinstance(i, result.Error) for i in r]): errors = [i for i in r if isinstance(i, result.Error)] for i in errors: logger.warning("{} error with code[{}],msg: {}".format( str(sql.raw), i.error_code, i.message)) ending_sql = "ROLLBACK" return_v = errors[0] c = [] for i in node: c.append(self._execute_ending_sql(ending_sql, i)) # 如果在 rollback 的时候异常,抛错给 app,即使数据库没有 rollback, # 也会在超时机制下回滚。 backend 遇到异常会关闭 session 触发 mysql # 的超时 # 如果在 commit 的时候出现异常,返回错误给客户端,客户端可以重试, # 成功就走正常流程,或者选择回滚,回滚就走事务回滚流程 await asyncio.gather(*c) if ending_sql == "ROLLBACK": return return_v # type: ignore return result.OK(1, 0, 2, 0, "", False)
async def acquire_lock(self, xid: int, node: str, table: str, lock_key: Dict[str, Any], sql: str) -> A2PCResponse: body = json.dumps({ "action": A2PCAction.ACQUIRE_LOCK, "xid": xid, "node": node, "table": table, "lock_key": lock_key, "context": sql }) n = (xid % self.mod) if self.mod > 0 else 0 server = self.services[n] url = "http://{}:{}/transactions".format(server[0], server[1]) req = HTTPRequest(url, "PUT", self.header, body) client = AsyncHTTPClient() try: logger.info("put: {}, param: {}".format(url, body)) response = await client.fetch(req) logger.info("response: {}".format(response.body)) return self._parse_result(response) except Exception as e: logger.warning("Error: %s" % e) raise e