Exemple #1
0
    def handle(self):
        try:
            fixed_header_bs = self._readexactly(BoltRequest.bolt_header_size())
            header = BoltRequest.bolt_header_from_stream(fixed_header_bs)
            call_type = header['ptype']
            cmdcode = header['cmdcode']

            class_name = self._readexactly(header['class_len'])
            bs = self._readexactly(header['header_len'])
            sofa_header = SofaHeader.from_bytes(bs)
            body = self._readexactly(header['content_len'])

            request_id = header['request_id']

            if cmdcode == CMDCODE.HEARTBEAT:
                self.wfile.write(HeartbeatResponse.response_to(request_id).to_stream())
                self.wfile.flush()
                return

            if cmdcode == CMDCODE.RESPONSE:
                raise ClientError("wrong cmdcode:[{}]".format(cmdcode))

            if class_name != "com.alipay.sofa.rpc.core.request.SofaRequest".encode():
                raise ClientError("wrong class_name:[{}]".format(class_name))

            service = sofa_header.get('sofa_head_target_service') or sofa_header.get('service')
            if not service:
                self.wfile.write(FailResponse.response_to(request_id, RESPSTATUS.CLIENT_SEND_ERROR).to_stream())
                self.wfile.flush()
                logger.error("Missing service name in sofa header [{}]".format(sofa_header))
                return
            method = sofa_header.get('sofa_head_method_name')
            if not method:
                self.wfile.write(FailResponse.response_to(request_id, RESPSTATUS.CLIENT_SEND_ERROR).to_stream())
                self.wfile.flush()
                logger.error("Missing method name in sofa header [{}]".format(sofa_header))
                return

            spanctx = tracer.extract(opentracing.Format.TEXT_MAP, sofa_header)
            # call servicehandler
            ret = self.service_handler.handle_request(spanctx, service, method, body)
            self.wfile.write(BoltResponse.response_to(ret, request_id=request_id).to_stream())
            self.wfile.flush()

        except OSError as e:
            if e.errno != ECONNRESET:
                raise

        except Exception as e:
            logger.error(traceback.format_exc())
Exemple #2
0
    async def _dispatch(self, call_type, request_id, sofa_header, body, *,
                        timeout_ms, codec, writer):
        """send request to handler"""
        service = sofa_header.get(
            'sofa_head_target_service') or sofa_header.get('service')
        if not service:
            await self._write_msg(
                writer,
                FailResponse.response_to(request_id,
                                         RESPSTATUS.CLIENT_SEND_ERROR,
                                         codec=codec).to_stream(),
            )
            logger.error(
                "Missing service name in sofa header [{}]".format(sofa_header))
            return
        method = sofa_header.get('sofa_head_method_name')
        if not method:
            await self._write_msg(
                writer,
                FailResponse.response_to(request_id,
                                         RESPSTATUS.CLIENT_SEND_ERROR,
                                         codec=codec).to_stream())
            logger.error(
                "Missing method name in sofa header [{}]".format(sofa_header))
            return

        spanctx = tracer.extract(opentracing.Format.TEXT_MAP, sofa_header)

        try:
            future = self.handler.handle_request(spanctx, service, method,
                                                 body)
        except NoProcessorError:
            await self._write_msg(
                writer,
                FailResponse.response_to(request_id,
                                         RESPSTATUS.NO_PROCESSOR,
                                         codec=codec).to_stream(),
            )
            return
        except Exception:
            await self._write_msg(
                writer,
                FailResponse.response_to(request_id,
                                         RESPSTATUS.SERVER_EXCEPTION,
                                         codec=codec).to_stream(),
            )
            return
        if PTYPE.ONEWAY == call_type:
            # Just return future
            return future

        try:
            afut = asyncio.wrap_future(future)
            result = await asyncio.wait_for(
                afut, timeout_ms / 1000 if timeout_ms > 0 else None)
        except (asyncio.CancelledError, asyncio.TimeoutError) as e:
            logger.error(
                "Task run cancelled/timeout in {}ms, service:[{}]: error:[{}]".
                format(timeout_ms, service, e))
            await self._write_msg(
                writer,
                FailResponse.response_to(request_id,
                                         RESPSTATUS.TIMEOUT,
                                         codec=codec).to_stream(),
            )
            return
        except Exception:
            logger.error(traceback.format_exc())
            await self._write_msg(
                writer,
                FailResponse.response_to(request_id,
                                         RESPSTATUS.UNKNOWN,
                                         codec=codec).to_stream(),
            )
            return

        if result:
            header = dict()
            tracer.inject(spanctx, opentracing.Format.TEXT_MAP, header)
            pkg = BoltResponse.response_to(result,
                                           request_id=request_id,
                                           codec=codec)
            try:
                await self._write_msg(writer, pkg.to_stream())
            except Exception:
                logger.error(traceback.format_exc())