Exemple #1
0
    def run_sync(self, func, timeout=None):
        """Starts the `IOLoop`, runs the given function, and stops the loop.

        The function must return either a yieldable object or
        ``None``. If the function returns a yieldable object, the
        `IOLoop` will run until the yieldable is resolved (and
        `run_sync()` will return the yieldable's result). If it raises
        an exception, the `IOLoop` will stop and the exception will be
        re-raised to the caller.

        The keyword-only argument ``timeout`` may be used to set
        a maximum duration for the function.  If the timeout expires,
        a `tornado.util.TimeoutError` is raised.

        This method is useful in conjunction with `tornado.gen.coroutine`
        to allow asynchronous calls in a ``main()`` function::

            @gen.coroutine
            def main():
                # do stuff...

            if __name__ == '__main__':
                IOLoop.current().run_sync(main)

        .. versionchanged:: 4.3
           Returning a non-``None``, non-yieldable value is now an error.
        """
        future_cell = [None]

        def run():
            try:
                result = func()
                if result is not None:
                    from tornado.gen import convert_yielded
                    result = convert_yielded(result)
            except Exception:
                future_cell[0] = Future()
                future_set_exc_info(future_cell[0], sys.exc_info())
            else:
                if is_future(result):
                    future_cell[0] = result
                else:
                    future_cell[0] = Future()
                    future_cell[0].set_result(result)
            self.add_future(future_cell[0], lambda future: self.stop())

        self.add_callback(run)
        if timeout is not None:
            timeout_handle = self.add_timeout(self.time() + timeout, self.stop)
        self.start()
        if timeout is not None:
            self.remove_timeout(timeout_handle)
        if not future_cell[0].done():
            raise TimeoutError('Operation timed out after %s seconds' %
                               timeout)
        return future_cell[0].result()
    def _reconnect(self):
        while self._retry_count < self._retry_max:
            self.__ensure_not_closed()
            self.__close_stream()
            try:
                self._stream = yield TCPClient().connect(self._address, self._port,
                                                         timeout=self._connect_timeout)
                break
            except (StreamClosedError, TimeoutError) as e:
                raise_e = False
                if self._retry_max <= 0:
                    raise_e = True
                if not isinstance(e, TimeoutError):
                    e = e.real_error
                    if e.args[0] not in RETRY_NETWORK_ERRNO:
                        raise_e = True
                else:
                    e = TimeoutError('time out')

                self._logger.debug('Connect error {}:{}, {}'.format(
                    self._address, self._port, e))
                if raise_e:
                    raise e

                self._retry_count += 1
                if self._retry_count < self._retry_max:
                    self._logger.debug('Connect retry {}:{} in {}s, {}/{}'.format(
                        self._address, self._port, self._retry_interval,
                        self._retry_count + 1, self._retry_max))
                    yield gen.sleep(self._retry_interval)

        self.__ensure_not_closed()
        if self._retry_count >= self._retry_max:
            raise RetryLimitExceeded(
                'Exceed retry limit {}/{}'.format(self._retry_count, self._retry_max))
        self._retry_count = -1
Exemple #3
0
 def timeout_callback():
     if not result.done():
         result.set_exception(TimeoutError("Timeout"))
     # In case the wrapped future goes on to fail, log it.
     future_add_done_callback(future, error_callback)
Exemple #4
0
    def run_sync(self, func: Callable, timeout: float = None) -> Any:
        """Starts the `IOLoop`, runs the given function, and stops the loop.

        The function must return either an awaitable object or
        ``None``. If the function returns an awaitable object, the
        `IOLoop` will run until the awaitable is resolved (and
        `run_sync()` will return the awaitable's result). If it raises
        an exception, the `IOLoop` will stop and the exception will be
        re-raised to the caller.

        The keyword-only argument ``timeout`` may be used to set
        a maximum duration for the function.  If the timeout expires,
        a `tornado.util.TimeoutError` is raised.

        This method is useful to allow asynchronous calls in a
        ``main()`` function::

            async def main():
                # do stuff...

            if __name__ == '__main__':
                IOLoop.current().run_sync(main)

        .. versionchanged:: 4.3
           Returning a non-``None``, non-awaitable value is now an error.

        .. versionchanged:: 5.0
           If a timeout occurs, the ``func`` coroutine will be cancelled.

        """
        future_cell = [None]  # type: List[Optional[Future]]

        def run() -> None:
            try:
                result = func()
                if result is not None:
                    from tornado.gen import convert_yielded

                    result = convert_yielded(result)
            except Exception:
                fut = Future()  # type: Future[Any]
                future_cell[0] = fut
                future_set_exc_info(fut, sys.exc_info())
            else:
                if is_future(result):
                    future_cell[0] = result
                else:
                    fut = Future()
                    future_cell[0] = fut
                    fut.set_result(result)
            assert future_cell[0] is not None
            self.add_future(future_cell[0], lambda future: self.stop())

        self.add_callback(run)
        if timeout is not None:

            def timeout_callback() -> None:
                # If we can cancel the future, do so and wait on it. If not,
                # Just stop the loop and return with the task still pending.
                # (If we neither cancel nor wait for the task, a warning
                # will be logged).
                assert future_cell[0] is not None
                if not future_cell[0].cancel():
                    self.stop()

            timeout_handle = self.add_timeout(self.time() + timeout,
                                              timeout_callback)
        self.start()
        if timeout is not None:
            self.remove_timeout(timeout_handle)
        assert future_cell[0] is not None
        if future_cell[0].cancelled() or not future_cell[0].done():
            raise TimeoutError("Operation timed out after %s seconds" %
                               timeout)
        return future_cell[0].result()