Beispiel #1
0
    def invoke_sync(self,
                    interface,
                    method_name,
                    content,
                    spanctx=None,
                    target_app="",
                    uid="",
                    timeout_ms=None,
                    **headers):
        """
        :param request:
        :param timeout: if timeout > 0, this specifies the maximum wait time, in
                   seconds
                   if timeout <= 0, the select() call won't block, and will
                   report the currently ready file objects
                   if timeout is None, select() will block until a monitored
                   file object becomes ready
        :return: serialized response content
        :raise: TimeoutError
        """
        assert isinstance(timeout_ms, (int, float))
        pkg = BoltResponse
        deadline = time.time() + timeout_ms / 1000 + 1
        req_id, c = self._raw_invoke(interface,
                                     method_name,
                                     content,
                                     target_app=target_app,
                                     uid=uid,
                                     spanctx=spanctx,
                                     timeout_ms=timeout_ms,
                                     **headers)

        with DefaultSelector() as sel:
            sel.register(c, EVENT_READ)
            total_size = pkg.bolt_header_size()
            resp_bytes = b''
            header = None
            while len(resp_bytes) < total_size:
                ready = sel.select(timeout=deadline - time.time())
                if not ready:
                    # timeout
                    c.close()
                    raise TimeoutError('Sync call timeout')
                for key, event in ready:
                    resp_bytes += key.fileobj.recv(total_size -
                                                   len(resp_bytes))
                if not header and len(resp_bytes) >= total_size:
                    header = pkg.bolt_header_from_stream(resp_bytes)
                    body_size = header['class_len'] + header[
                        'header_len'] + header['content_len']
                    total_size += body_size
        self._get_pool(interface).put_conn(c)

        resp = pkg.bolt_content_from_stream(
            resp_bytes[pkg.bolt_header_size():], header)
        if resp.request_id != req_id:
            raise ServerError("RequestId not match")
        if resp.respstatus != RESPSTATUS.SUCCESS:
            raise ServerError.from_statuscode(resp.respstatus)
        return resp.content
Beispiel #2
0
    async def _recv_response(self, reader, writer):
        """
        wait response and put it in response_mapping, than notify the invoke coro
        :param reader:
        :return:
        """
        while True:
            pkg = None
            try:
                fixed_header_bs = await reader.readexactly(
                    BoltResponse.bolt_header_size())
                header = BoltResponse.bolt_header_from_stream(fixed_header_bs)
                bs = await reader.readexactly(header['class_len'] +
                                              header['header_len'] +
                                              header['content_len'])
                pkg = BoltResponse.bolt_content_from_stream(bs, header)
                if pkg.class_name != BoltResponse.class_name:
                    raise ServerError("wrong class_name:[{}]".format(
                        pkg.class_name))
                if pkg.cmdcode == CMDCODE.HEARTBEAT:
                    continue
                elif pkg.cmdcode == CMDCODE.REQUEST:
                    # raise error, the connection will be dropped
                    raise ServerError("wrong cmdcode:[{}]".format(pkg.cmdcode))
                if pkg.respstatus != RESPSTATUS.SUCCESS:
                    raise ServerError.from_statuscode(pkg.respstatus)
                if pkg.request_id not in self.request_mapping:
                    continue
                self.response_mapping[pkg.request_id] = pkg

            except PyboltError as e:
                logger.error(e)
            except (asyncio.CancelledError, EOFError,
                    ConnectionResetError) as e:
                logger.error(e)
                writer.close()
                break
            except Exception:
                logger.error(traceback.format_exc())
                writer.close()
                break
            finally:
                with suppress(AttributeError, KeyError):
                    # wake up the coro
                    event = self.request_mapping.pop(pkg.request_id)
                    event.set()