def __call__(self, on_error, func, *args): with self._workers_lock: self._promise += 1 ack = Ack() queued = False while not ack.is_set(): if not queued: try: if __debug__: syncqueuelogger.debug('Queue task') self._queue.put_nowait((ack, on_error, func, args)) if __debug__: syncqueuelogger.debug('Task queued') with self._workers_lock: self._promise -= 1 queued = True except Full: if __debug__: syncqueuelogger.debug( 'Task not queued - no empty slots. Launch new worker (%s, %s)', self, self._pending_workers) pass if not queued or not ack.wait(timeout=self.MAX_TASK_ACK_TIME, probe=0.1): with self._workers_lock: if self._closed: if __debug__: syncqueuelogger.debug( 'Queue (%s) closed, do not start new worker', self) self._workers += 1 if self._workers > self._max_workers: self._max_workers = self._workers if __debug__: syncqueuelogger.info( 'Max workers(%s): %s', self, self._max_workers) thread = Thread( target=self._dispatch_request_worker, name="SyncQueue Dispatcher" ) thread.daemon = True thread.start()
class PupyConnection(Connection): __slots__ = ('_close_lock', '_sync_events_lock', '_async_events_lock', '_sync_events', '_sync_raw_replies', '_sync_raw_exceptions', '_last_recv', '_ping', '_ping_timeout', '_serve_timeout', '_last_ping', '_default_serve_timeout', '_queue', '_config', '_timer_event', '_timer_event_last') def __init__(self, pupy_srv, *args, **kwargs): self._close_lock = Lock() self._sync_events_lock = Lock() self._async_events_lock = Lock() self._sync_events = {} self._sync_raw_replies = {} self._sync_raw_exceptions = {} self._last_recv = time.time() self._ping = False self._ping_timeout = 30 self._serve_timeout = 10 self._last_ping = None self._default_serve_timeout = 5 self._queue = SyncRequestDispatchQueue.get_queue() self._timer_event = None self._timer_event_last = None if 'ping' in kwargs: ping = kwargs.pop('ping') else: ping = None if 'timeout' in kwargs: timeout = kwargs.pop('timeout') else: timeout = None if 'timer_event' in kwargs: self._timer_event = kwargs.pop('timer_event') if ping or timeout: self.set_pings(ping, timeout) kwargs['_lazy'] = True Connection.__init__(self, *args, **kwargs) if pupy_srv: self._local_root.pupy_srv = pupy_srv if 'config' in kwargs: self._config.update(kwargs['config']) next(self._seqcounter) def _on_sync_request_exception(self, exc): if not isinstance(exc, EOFError): logger.exception(exc) self.close() def consume(self): return self._channel.consume() def wake(self): self._channel.wake() def set_pings(self, ping=None, timeout=None): if ping is not None: try: self._serve_timeout = int(ping) except: self._serve_timeout = 10 self._ping = ping and ping not in ('0', '-1', 'N', 'n', 'false', 'False', 'no', 'No') self._ping = bool(ping) if timeout: try: self._ping_timeout = int(timeout) except: self._ping_timeout = 2 return self.get_pings() def get_pings(self): if self._ping: return self._serve_timeout, self._ping_timeout else: return None, None def sync_request(self, handler, *args): seq = self._send_request(handler, args) if __debug__: synclogger.debug('Sync request wait: {}'.format(seq)) self._sync_events[seq].wait() if __debug__: synclogger.debug('Sync request wait: {} - complete'.format(seq)) del self._sync_events[seq] if __debug__: synclogger.debug('Sync request process: {}'.format(seq)) is_response = False is_exception = False with self._sync_events_lock: is_response = seq in self._sync_raw_replies is_exception = seq in self._sync_raw_exceptions if is_response: if __debug__: synclogger.debug('Dispatch sync reply: {} - start'.format(seq)) Connection._dispatch_reply(self, seq, self._sync_raw_replies.pop(seq)) if __debug__: synclogger.debug( 'Dispatch sync reply: {} - complete'.format(seq)) if is_exception: if __debug__: synclogger.debug( 'Dispatch sync exception: {} - start'.format(seq)) Connection._dispatch_exception(self, seq, self._sync_raw_exceptions.pop(seq)) if __debug__: synclogger.debug( 'Dispatch sync exception: {} - complete'.format(seq)) if __debug__: synclogger.debug('Sync request: {} - complete'.format(seq)) if self.closed: raise EOFError('Connection was closed, seq: {}'.format(seq)) isexc, obj = self._sync_replies.pop(seq) if isexc: raise obj else: return obj def _send_request(self, handler, args, async=None): seq = next(self._seqcounter) if async: if __debug__: logger.debug('Async request: {}'.format(seq)) self._async_callbacks[seq] = async else: if __debug__: synclogger.debug('Sync request: {}'.format(seq)) self._sync_events[seq] = Ack() self._send(consts.MSG_REQUEST, seq, (handler, self._box(args))) if __debug__: synclogger.debug('Request submitted: {}'.format(seq)) return seq