def __internal_send(self, request: Event) -> ResultStatus: with self.lock: # Browse all queues to_delete = [] for index in self.__queues.keys(): # Reckon interrupted time interrupted_time = ( (time.time() - self.__interrupt_times[index]) if index in self.__interrupt_times and self.__interrupt_times[index] is not None else None ) retain_timeout = RpcStaticConfig.EVENT_RETAIN_TIMEOUT.int_val # Interrupted queue + retain timeout expired? if interrupted_time is not None and interrupted_time >= retain_timeout: # Yes, forget event queue self.logger.info(f"Deleting interrupted event queue #{index} (retain timeout: {interrupted_time} >= {retain_timeout})") to_delete.append(index) else: # Still active queue: push event self.__queues[index].put_nowait(request) # Forget timed out events (if any) if len(to_delete): for index in to_delete: del self.__queues[index] del self.__interrupt_times[index] self._persist_queues() return ResultStatus()
def s_method2(self, request: SampleRequest) -> ResultStatus: for foo in ["abc", "def", "ghi", request.foo]: # Raise exception on "error" string if foo == "error": raise RpcException("Sample error occurred", rc=ResultCode.ERROR_PARAM_INVALID) yield ResultStatus(r=Result(msg=foo))
def proxy_register(self, request: ProxyRegisterRequest) -> ResultStatus: # Verify input params services = self.__check_proxy_names(request) if len(request.version) == 0 or request.port == 0: raise RpcException( "Missing input parameter in request (one of version or port)", ResultCode.ERROR_PARAM_MISSING) # Ready to update service proxy info with self.lock: for srv in services: # Update info srv.version = request.version srv.proxy_port = request.port srv.proxy_host = request.host # Persist proxy info self.__persist_proxies() # Send proxy registration event if self.__can_send_events: # pragma: no branch self.client.events.send( RpcEvent( name="RPC_PROXY_REGISTER", properties=[ EventProperty(name="names", value=",".join(request.names)), EventProperty(name="version", value=request.version), EventProperty(name="port", value=str(request.port)), EventProperty(name="host", value=request.host), ], )) return ResultStatus()
def interrupt(self, request: EventInterrupt) -> ResultStatus: # Known index? q = self.__get_queue(request.client_id) # Refuse to interrupt again already interrupted queue with self.lock: if request.client_id in self.__interrupt_times and self.__interrupt_times[request.client_id] is not None: raise RpcException(f"Already interrupted ID: {request.client_id}", ResultCode.ERROR_STATE_UNEXPECTED) # Put "None" event (will wait until listen loop is over) q.put(None) return ResultStatus()
def report_exception(self, context, e: Exception): # Something happened during the RPC execution stack = "".join(traceback.format_tb(e.__traceback__)) self.logger.error(f"Exception occurred: {e}\n{stack}") # Extract RC if this was a known error rc = e.rc if isinstance(e, RpcException) else ResultCode.ERROR # Build result according to return type r = Result(code=rc, msg=str(e), stack=stack) return ResultStatus( r=r) if self.return_type is None else self.return_type(r=r)
def method1(self, request: Empty) -> ResultStatus: self.logger.info("In SampleServicer.method1!!!") # Sleep if requested if self.wait_a_bit: time.sleep(3) # Use auto-client to access other services (only if not shutdown in the meantime) s = None if not self.is_shutdown: s = self.client.srv.info(Filter()) return ResultStatus(r=Result( msg=f"Found info count: {len(s.items) if s is not None else None}") )
def shutdown(self, request: ShutdownRequest = None) -> ResultStatus: """ Shuts down this RPC server instance """ # Only if not shutdown yet if self.__server is not None: # Make sure we won't enter here twice terminating_server = self.__server self.__server = None # Stop server and wait for termination self.logger.debug( f"Shutting down RPC server on port {self.__port}; stop accepting new requests" ) terminating_server.stop(RpcStaticConfig.SHUTDOWN_GRACE.float_val) # Shutdown all managers self.logger.debug("Shutting down all managers") for descriptor in self.__real_descriptors: descriptor.manager._shutdown() # Is this an RPC call? if request is not None: # Yes --> delegate termination to its own thread, to return immediately from this request Thread(target=self.__finalize_shutdown, kwargs={ "terminating_server": terminating_server, "request": request }, name="ShutdownThread").start() else: # Finalize shutdown immediately (internal call) self.__finalize_shutdown(terminating_server, None) # Always OK return ResultStatus()
def proxy_forget(self, request: Filter) -> ResultStatus: # Verify input params services = self.__check_proxy_names(request) # Ready to update service proxy info with self.lock: for srv in services: # Update info srv.proxy_port = 0 srv.proxy_host = "" # Persist proxy info self.__persist_proxies() # Send proxy forget event if self.__can_send_events: # pragma: no branch self.client.events.send( RpcEvent(name="RPC_PROXY_FORGET", properties=[ EventProperty(name="names", value=",".join(request.names)) ])) return ResultStatus()
def s_method1(self, request: Iterable[SampleRequest]) -> ResultStatus: out = "" for req in request: self.logger.info(f"request: {req.foo}") out += req.foo return ResultStatus(r=Result(msg=out))