예제 #1
0
    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()
예제 #2
0
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