def update_last_known_state(self, chain_id: int, version: int, timestamp_usecs: int) -> None: """update last known server state Raises InvalidServerResponse if given chain_id mismatches with previous value Raises StaleResponseError if version or timestamp_usecs is less than previous values """ curr = self._last_known_server_state if curr.chain_id != -1 and curr.chain_id != chain_id: raise InvalidServerResponse( f"last known chain id {curr.chain_id}, " f"but got {chain_id}") if curr.version > version: raise StaleResponseError( f"last known version {curr.version} > {version}") if curr.timestamp_usecs > timestamp_usecs: raise StaleResponseError( f"last known timestamp_usecs {curr.timestamp_usecs} > {timestamp_usecs}" ) self._last_known_server_state = State( chain_id=chain_id, version=version, timestamp_usecs=timestamp_usecs, )
async def _send_http_request( self, url: str, request: typing.Dict[str, typing.Any], ignore_stale_response: bool, ) -> typing.Dict[str, typing.Any]: self._logger.debug("http request body: %s", request) headers = {"User-Agent": USER_AGENT_HTTP_HEADER} async with self._session.post(url, json=request, headers=headers) as response: self._logger.debug("http response body: %s", response.text) response.raise_for_status() try: json = await response.json() except ValueError as e: raise InvalidServerResponse( f"Parse response as json failed: {e}, response: {response.text}" ) # check stable response before check jsonrpc error try: self.update_last_known_state( json.get("diem_chain_id"), json.get("diem_ledger_version"), json.get("diem_ledger_timestampusec"), ) except StaleResponseError as e: if not ignore_stale_response: raise e return json
def execute_without_retry( self, method: str, params: typing.List[typing.Any], # pyre-ignore result_parser: typing.Optional[typing.Callable] = None, # pyre-ignore ignore_stale_response: typing.Optional[bool] = None, ): """execute JSON-RPC method call without retry any error. Raises InvalidServerResponse if server response does not match [JSON-RPC SPEC 2.0](https://www.jsonrpc.org/specification), or response result can't be parsed. Raises StaleResponseError if ignore_stale_response is True, otherwise ignores it and continue. Raises JsonRpcError if server JSON-RPC response with error object. Raises NetworkError if send http request failed, or received server response status is not 200. """ request = { "jsonrpc": "2.0", "id": 1, "method": method, "params": params or [], } try: json = self._rs.send_request(self, request, ignore_stale_response or False) if "error" in json: err = json["error"] raise JsonRpcError(f"{err}") if "result" in json: if result_parser: return result_parser(json["result"]) return raise InvalidServerResponse( f"No error or result in response: {json}") except requests.RequestException as e: raise NetworkError( f"Error in connecting to server: {e}\nPlease retry...") except parser.ParseError as e: raise InvalidServerResponse( f"Parse result failed: {e}, response: {json}")