def _dispatch_batch(self, msgs): def _process(): self._log_info(u'Received batch: ' + six.text_type(msgs)) rfs = RpcForServices(self.rpc) promises = [] nthreads = [] for msg in msgs: if 'id' in msg: promises.append(self._handle_batch_request(msg, rfs)) else: nthreads.append( self._execute_notification(msg, rfs, False)) results = list(map(lambda p: p.wait(), promises)) if results: if rfs.aborted: self._log_info( 'Connection aborted during batch processing.') return self.rpc.socket_queue.put(results) self._log_info( u'Sent batch response: ' + six.text_type(results)) else: self._log_info(u'Notification-only batch processed.') if not rfs.close_after_response_requested: for nthread in [t for t in nthreads if t]: nthread.join() if rfs.close_after_response_requested: self.rpc.close() self._log_info( u'RPC closed due to invocation by Request or ' u'Notification handler.') self._active_threads.append(spawn(self.rpc.threading_model, _process))
def join(self, timeout=None): def _totaljoiner(): self._thread.join() for thr in self._active_threads: thr.join() joiner_thread = spawn(self.rpc.threading_model, _totaljoiner) joiner_thread.join(timeout)
def _execute_notification(self, msg, rfs, after_effects): def _execute(): method_name = msg['method'] args, kwargs = self._get_params(msg) method = self.rpc.services._notification_handlers.get(method_name) if method: try: self._log_info( u'Received notification: ' + six.text_type(msg)) method(self.rpc.services, rfs, *args, **kwargs) except Exception as e: self._log_error(e) if (after_effects and not rfs.aborted and rfs.close_after_response_requested): self.rpc.close() self._log_info( u'RPC closed due to invocation by ' u'Notification handler.') else: self._log_error( u'Unrecognized notification from peer: ' + six.text_type(msg)) tm = self.rpc.concurrent_notification_handling if tm is None: _execute() return None else: thr = spawn(tm, _execute) self._active_threads.append(thr) return thr
def __init__(self, rpc): ''' :param rpc: Rpc parent object. :type rpc: RpcBase ''' # {"<msg_id>": <promise>, ...} self._responses = {} # { ("<msg_id>", "<msg_id>",): promise, ...} self._batch_responses = {} # Active threads self._active_threads = [] self.rpc = rpc self.conn_label = six.text_type( self.rpc.connection_id and '%s: ' % self.rpc.connection_id) self._thread = spawn(self.rpc.threading_model, self.run)
def _handle_batch_request(self, msg, rfs): def _execute(promise): self._log_info(u'Handling batch request: ' + six.text_type(msg)) response = self._execute_request(msg, rfs) self._log_info( u'Generated batch response: ' + six.text_type(response)) promise.set(response) tm = self.rpc.concurrent_request_handling if tm is None: promise = new_promise(ThreadingModel.THREADS) _execute(promise) else: promise = new_promise(tm) self._active_threads.append(spawn(tm, _execute, promise)) return promise
def __init__(self, socket, codec, threading_model): ''' :param socket: Socket connected to rpc peer node. :type socket: socket.socket :param codec: Codec converting python data to/from binary data :type codec: BSONCodec or JSONCodec :param threading_model: Threading model :type threading_model: bsonrpc.options.ThreadingModel.GEVENT or bsonrpc.options.ThreadingModel.THREADS ''' self.socket = socket self.codec = codec self._queue = new_queue(threading_model) self._lock = new_lock(threading_model) self._receiver_thread = spawn(threading_model, self._receiver) self._closed = False
def _handle_request(self, msg): def _execute(): self._log_info(u'Received request: ' + six.text_type(msg)) rfs = RpcForServices(self.rpc) response = self._execute_request(msg, rfs) if rfs.aborted: self._log_info(u'Connection aborted in request handler.') return self.rpc.socket_queue.put(response) self._log_info(u'Sent response: ' + six.text_type(response)) if rfs.close_after_response_requested: self.rpc.close() self._log_info( u'RPC closed due to invocation by Request handler.') tm = self.rpc.concurrent_request_handling if tm is None: _execute() else: self._active_threads.append(spawn(tm, _execute))