def _ws_send_recv(self): to_server = SimulatorToServer() self._on_send(to_server) log.pb("to_server: {}".format(MessageToJson(to_server))) if (to_server.message_type): out_bytes = to_server.SerializeToString() try: yield self._ws.write_message(out_bytes, binary=True) except (StreamClosedError, WebSocketClosedError) as e: raise BonsaiServerError( "Websocket connection closed. Code: {}, Reason: {}".format( self._ws.close_code, self._ws.close_reason)) # read response from server in_bytes = yield self._ws.read_message() if in_bytes is None: raise BonsaiServerError( "Websocket connection closed. Code: {}, Reason: {}".format( self._ws.close_code, self._ws.close_reason)) from_server = ServerToSimulator() from_server.ParseFromString(in_bytes) log.pb("from_server: {}".format(MessageToJson(from_server))) self._on_recv(from_server)
def _handler(self, http_method, url, *args, **kwargs): try: return func(self, http_method, url, *args, **kwargs) except requests.exceptions.ConnectionError: message = \ "{} Request failed. Unable to connect to domain: " \ "{}".format(http_method, url) raise BonsaiServerError(message) except requests.exceptions.Timeout: message = "{} Request failed. Request to {} timed out".format( http_method, url) raise BonsaiServerError(message)
def run(self): """ Run loop called from Simulator. Encapsulates one round trip to the backend, which might include a simulation loop. """ # Grab a web socket connection if needed if self._ws is None: message = yield self._connect() # If the connection failed, report if message is not None: raise BonsaiServerError( "Error while connecting to websocket: {}".format(message)) # If there is a batch of predictions cued up, step through it if self._prev_message_type == ServerToSimulator.PREDICTION: for step in self._sim_steps: self._advance(step) # send message to server to_server = SimulatorToServer() self._on_send(to_server) if (to_server.message_type): out_bytes = to_server.SerializeToString() try: yield self._ws.write_message(out_bytes, binary=True) except (StreamClosedError, WebSocketClosedError) as e: raise BonsaiServerError( "Websocket connection closed. Code: {}, Reason: {}".format( self._ws.close_code, self._ws.close_reason)) # read response from server in_bytes = yield self._ws.read_message() if in_bytes is None: raise BonsaiServerError( "Websocket connection closed. Code: {}, Reason: {}".format( self._ws.close_code, self._ws.close_reason)) from_server = ServerToSimulator() from_server.ParseFromString(in_bytes) self._on_recv(from_server) if self._prev_message_type == ServerToSimulator.FINISHED: yield self._ws.close() raise gen.Return(False) # You've come this far, celebrate! raise gen.Return(True)
def _handle_message(self, message): """ Handles error messages returned from initial connection attempt """ log.network('Handling the following message returned from ws:' ' {}'.format(message)) if isinstance(message, HTTPError): if message.code == 401: raise BonsaiServerError( 'Error while connecting to websocket: {}. ' 'Please run \'bonsai configure\' again.'.format(message)) if message.code == 404: raise BonsaiServerError( 'Error while connecting to websocket: {}'.format(message)) if not self._retry_timeout_seconds: raise BonsaiServerError( 'Error while connecting to websocket: {}'.format(message)) log.network('Error while connecting to websocket: {}'.format(message))
def _try_http_request(self, http_method, url, data): """ param: http_method -> String: Http method for request, I.E. "GET" param: url -> String: url to send request param: data -> JSON Formatted Dictionary: json data to send with request """ log.api('Sending {} request to {}'.format(http_method, url)) request_id = str(uuid4()) try: if http_method == 'GET': response = self._session.get( url=url, allow_redirects=False, timeout=self._timeout, headers={'RequestId': request_id}) elif http_method == 'PUT': response = self._session.put( url=url, data=data, headers={'RequestId': request_id}, allow_redirects=False, timeout=self._timeout) elif http_method == 'POST': response = self._session.post( url=url, data=data, allow_redirects=False, timeout=self._timeout, headers={'RequestId': request_id}) elif http_method == 'DELETE': response = self._session.delete( url=url, allow_redirects=False, timeout=self._timeout, headers={'RequestId': request_id}) else: raise UsageError('UNSUPPORTED HTTP METHOD') except requests.exceptions.ConnectionError: message = \ "Connection Error, {} Request failed. Unable to connect to " \ "domain: {}\nRequest ID: {}".format(http_method, url, request_id) raise BonsaiServerError(message) except requests.exceptions.Timeout: message = "{} Request failed. Request to {} timed out" \ "\nRequest ID: {}".format(http_method, url, request_id) raise BonsaiServerError(message) try: response.raise_for_status() self._log_response(response, request_id) except requests.exceptions.HTTPError as err: self._handle_http_error(response, request_id) return self._dict(response)
def _handle_http_error(response): """ :param response: The response from the server. """ try: message = 'Request failed with error message:\n{}'.format( response.json()["error"]) except ValueError: message = 'Request failed.' raise BonsaiServerError(message)
def get_next_event(self): """ Update the internal event machine and return the next event for processing""" # Grab a web socket connection if needed if self._ws is None: message = yield self._connect() # If the connection failed, report if message is not None: raise BonsaiServerError( "Error while connecting to websocket: {}".format(message)) if self._prev_message_type == ServerToSimulator.PREDICTION: if self._prev_step_terminal[0]: self._prev_step_terminal[0] = False self._prev_step_finish = True event = EpisodeFinishEvent() else: event = self._process_sim_step() if event is not None: raise gen.Return(event) yield self._ws_send_recv() pmt = self._prev_message_type if pmt == ServerToSimulator.ACKNOWLEDGE_REGISTER: if self._sim.predict: self._initial_state = self._new_state_message() event = EpisodeStartEvent(self._init_properties, self._initial_state) self._prev_step_finish = False else: event = UnknownEvent() if pmt == ServerToSimulator.SET_PROPERTIES or \ pmt == ServerToSimulator.RESET: event = UnknownEvent() elif pmt == ServerToSimulator.STOP: if self._prev_step_finish: event = UnknownEvent() self._prev_step_finish = False else: event = EpisodeFinishEvent() elif pmt == ServerToSimulator.START: self._initial_state = self._new_state_message() event = EpisodeStartEvent(self._init_properties, self._initial_state) self._prev_step_finish = False elif pmt == ServerToSimulator.PREDICTION: event = self._process_sim_step() elif pmt == ServerToSimulator.FINISHED: event = FinishedEvent() else: event = UnknownEvent() raise gen.Return(event)
def _handle_message(self, message): """ Handles error messages returned from initial connection attempt """ log.network( 'Handling the following message returned from ws:' ' {}'.format(message)) if isinstance(message, WSServerHandshakeError): if message.code == 401: raise BonsaiServerError( 'Error while connecting to websocket: 401 - Unauthorized. ' 'Please run \'bonsai configure\' again.') if message.code == 403: raise BonsaiServerError( 'Error while connecting to websocket: 403 - Forbidden. ' 'You may be using deprecated authorization methods. ' 'Please run \'bonsai configure\' again.') if message.code == 404: raise BonsaiServerError( 'Error while connecting to websocket: 404 - Not Found.') if not self._retry_timeout_seconds: raise BonsaiServerError( 'Error while connecting to websocket: {}'.format(message)) log.network('Error while connecting to websocket: {}'.format(message))
def handle_disconnect(self, message=None): log.network('Handling disconnect') self._thread_stop.set() if message: self._handle_message(message) if self._ws: if self._websocket_should_not_reconnect(): raise BonsaiServerError( 'Websocket connection closed. Code: {}, Reason: {}'.format( self._ws.close_code, self._ws.close_reason)) log.network('ws_close_code: {}, ws_close_reason: {}.'.format( self._ws.close_code, self._ws.close_reason)) self.close() log.network('Disconnect handled.')
def _handle_http_error(response, request_id): """ :param response: The response from the server. """ try: message = 'Request failed with error code "{}", error message:\n{}'.format( response.json()["error"]["code"], response.json()["error"]["message"]) except ValueError: message = 'Request failed.' message += '\nRequest ID: {}'.format(request_id) try: message += '\nSpan ID: {}'.format(response.headers['SpanID']) except KeyError: pass raise BonsaiServerError(message)
def _raise(msg): raise BonsaiServerError( "Received unknown message ({}) from server".format( msg.message_type))
def _unsupported(self, to_server): descriptor = ServerToSimulator.MessageType.DESCRIPTOR raise BonsaiServerError("Unexpected Message during {}: {}".format( "prediction" if self._sim.predict else "training", descriptor.values_by_number[self._prev_message_type].name))