Esempio n. 1
0
    def status(self, throw_except=True, internal_storage=None):
        """
        Return the status returned by the call.
        If the call raised an exception, this method will raise the same exception
        If the future is cancelled before completing then CancelledError will be raised.

        :param check_only: Return None immediately if job is not complete. Default False.
        :param throw_except: Reraise exception if call raised. Default true.
        :param storage_handler: Storage handler to poll cloud storage. Default None.
        :return: Result of the call.
        :raises CancelledError: If the job is cancelled before completed.
        :raises TimeoutError: If job is not complete after `timeout` seconds.
        """
        if self._state == ResponseFuture.State.New:
            raise ValueError("task not yet invoked")

        if self._state in [
                ResponseFuture.State.Ready, ResponseFuture.State.Success
        ]:
            return self._call_status

        if internal_storage is None:
            internal_storage = InternalStorage(self._storage_config)

        if self._call_status is None:
            check_storage_path(internal_storage.get_storage_config(),
                               self._storage_path)
            self._call_status = internal_storage.get_call_status(
                self.executor_id, self.job_id, self.call_id)
            self._status_query_count += 1

            while self._call_status is None:
                time.sleep(self.GET_RESULT_SLEEP_SECS)
                self._call_status = internal_storage.get_call_status(
                    self.executor_id, self.job_id, self.call_id)
                self._status_query_count += 1

        self.stats['host_status_done_tstamp'] = time.time()
        self.stats['host_status_query_count'] = self._status_query_count
        self.activation_id = self._call_status.pop('activation_id', None)

        if self._call_status['type'] == '__init__':
            self._set_state(ResponseFuture.State.Running)
            return self._call_status

        if self._call_status['exception']:
            self._set_state(ResponseFuture.State.Error)
            self._exception = pickle.loads(eval(self._call_status['exc_info']))

            msg1 = (
                'ExecutorID {} | JobID {} - There was an exception - Activation '
                'ID: {}'.format(self.executor_id, self.job_id,
                                self.activation_id))

            if not self._call_status.get('exc_pickle_fail', False):
                fn_exctype = self._exception[0]
                fn_exc = self._exception[1]
                if fn_exc.args and fn_exc.args[0] == "HANDLER":
                    self._handler_exception = True
                    try:
                        del fn_exc.errno
                    except Exception:
                        pass
                    fn_exc.args = (fn_exc.args[1], )
            else:
                fn_exctype = Exception
                fn_exc = Exception(self._exception['exc_value'])
                self._exception = (fn_exctype, fn_exc,
                                   self._exception['exc_traceback'])

            def exception_hook(exctype, exc, trcbck):
                if exctype == fn_exctype and str(exc) == str(fn_exc):
                    logger.warning(msg1)
                    if self._handler_exception:
                        msg2 = 'Exception: {} - {}'.format(
                            fn_exctype.__name__, fn_exc)
                        logger.warning(msg2)
                    else:
                        traceback.print_exception(*self._exception)
                else:
                    sys.excepthook = sys.__excepthook__
                    traceback.print_exception(exctype, exc, trcbck)

            if throw_except:
                sys.excepthook = exception_hook
                time.sleep(1)
                reraise(*self._exception)
            else:
                logger.warning(msg1)
                msg2 = 'Exception: {} - {}'.format(self._exception[0].__name__,
                                                   self._exception[1])
                logger.warning(msg2)
                return None

        for key in self._call_status:
            if any(ss in key for ss in ['time', 'tstamp', 'count', 'size']):
                self.stats[key] = self._call_status[key]

        self.stats['worker_exec_time'] = round(
            self.stats['worker_end_tstamp'] -
            self.stats['worker_start_tstamp'], 8)
        total_time = format(round(self.stats['worker_exec_time'], 2), '.2f')

        log_msg = (
            'ExecutorID {} | JobID {} - Got status from call {} - Activation '
            'ID: {} - Time: {} seconds'.format(self.executor_id, self.job_id,
                                               self.call_id,
                                               self.activation_id,
                                               str(total_time)))
        logger.debug(log_msg)
        self._set_state(ResponseFuture.State.Ready)

        if not self._call_status['result']:
            self._produce_output = False

        if not self._produce_output:
            self._set_state(ResponseFuture.State.Success)

        if 'new_futures' in self._call_status:
            self.result(throw_except=throw_except,
                        internal_storage=internal_storage)

        return self._call_status
Esempio n. 2
0
    def status(self,
               throw_except=True,
               internal_storage=None,
               check_only=False):
        """
        Return the status returned by the call.
        If the call raised an exception, this method will raise the same exception
        If the future is cancelled before completing then CancelledError will be raised.

        :param check_only: Return None immediately if job is not complete. Default False.
        :param throw_except: Reraise exception if call raised. Default true.
        :param storage_handler: Storage handler to poll cloud storage. Default None.
        :return: Result of the call.
        :raises CancelledError: If the job is cancelled before completed.
        :raises TimeoutError: If job is not complete after `timeout` seconds.
        """
        if self._state == ResponseFuture.State.New:
            raise ValueError("task not yet invoked")

        if self.success or self.done:
            return self._call_status

        if self.ready and self._new_futures:
            self._set_state(ResponseFuture.State.Done)
            return self._call_status

        if self._call_status is None or self._call_status['type'] == '__init__':
            if internal_storage is None:
                internal_storage = InternalStorage(self._storage_config)
            check_storage_path(internal_storage.get_storage_config(),
                               self._storage_path)
            self._call_status = internal_storage.get_call_status(
                self.executor_id, self.job_id, self.call_id)
            self._status_query_count += 1

            if check_only:
                return self._call_status

            while self._call_status is None:
                time.sleep(self.GET_RESULT_SLEEP_SECS)
                self._call_status = internal_storage.get_call_status(
                    self.executor_id, self.job_id, self.call_id)
                self._status_query_count += 1
            self._host_status_done_tstamp = time.time()

        self.stats[
            'host_status_done_tstamp'] = self._host_status_done_tstamp or time.time(
            )
        self.stats['host_status_query_count'] = self._status_query_count
        self.activation_id = self._call_status['activation_id']

        if 'logs' in self._call_status:
            self.logs = zlib.decompress(
                base64.b64decode(self._call_status['logs'].encode())).decode()
            job_key = create_job_key(self.executor_id, self.job_id)
            log_file = os.path.join(LOGS_DIR, job_key + '.log')
            header = "Activation: '{}' ({})\n[\n".format(
                self.runtime_name, self.activation_id)
            tail = ']\n\n'
            output = self.logs.replace('\r',
                                       '').replace('\n', '\n    ',
                                                   self.logs.count('\n') - 1)
            with open(log_file, 'a') as lf:
                lf.write(header + '    ' + output + tail)
            with open(FN_LOG_FILE, 'a') as lf:
                lf.write(header + '    ' + output + tail)

        if self._call_status['exception']:
            self._set_state(ResponseFuture.State.Error)
            self._exception = pickle.loads(eval(self._call_status['exc_info']))

            msg1 = (
                'ExecutorID {} | JobID {} - There was an exception - Activation '
                'ID: {}'.format(self.executor_id, self.job_id,
                                self.activation_id))

            if not self._call_status.get('exc_pickle_fail', False):
                fn_exctype = self._exception[0]
                fn_exc = self._exception[1]
                if fn_exc.args and fn_exc.args[0] == "HANDLER":
                    self._handler_exception = True
                    try:
                        del fn_exc.errno
                    except Exception:
                        pass
                    fn_exc.args = (fn_exc.args[1], )
            else:
                fn_exctype = Exception
                fn_exc = Exception(self._exception['exc_value'])
                self._exception = (fn_exctype, fn_exc,
                                   self._exception['exc_traceback'])

            def exception_hook(exctype, exc, trcbck):
                if exctype == fn_exctype and str(exc) == str(fn_exc):
                    logger.warning(msg1)
                    if self._handler_exception:
                        msg2 = 'Exception: {} - {}'.format(
                            fn_exctype.__name__, fn_exc)
                        logger.warning(msg2)
                    else:
                        traceback.print_exception(*self._exception)
                else:
                    sys.excepthook = sys.__excepthook__
                    traceback.print_exception(exctype, exc, trcbck)

            if throw_except:
                sys.excepthook = exception_hook
                reraise(*self._exception)
            else:
                logger.warning(msg1)
                msg2 = 'Exception: {} - {}'.format(self._exception[0].__name__,
                                                   self._exception[1])
                logger.warning(msg2)
                return None

        for key in self._call_status:
            if any(ss in key
                   for ss in ['time', 'tstamp', 'count', 'size', 'container']):
                self.stats[key] = self._call_status[key]

        self.stats['worker_exec_time'] = round(
            self.stats['worker_end_tstamp'] -
            self.stats['worker_start_tstamp'], 8)
        total_time = format(round(self.stats['worker_exec_time'], 2), '.2f')

        logger.debug(
            'ExecutorID {} | JobID {} - Got status from call {} - Activation '
            'ID: {} - Time: {} seconds'.format(self.executor_id, self.job_id,
                                               self.call_id,
                                               self.activation_id,
                                               str(total_time)))

        self._set_state(ResponseFuture.State.Success)

        if not self._call_status['result']:
            self._produce_output = False

        if not self._produce_output:
            self._set_state(ResponseFuture.State.Done)

        if 'new_futures' in self._call_status and not self._new_futures:
            new_futures = pickle.loads(eval(self._call_status['new_futures']))
            self._new_futures = [
                new_futures
            ] if type(new_futures) == ResponseFuture else new_futures
            self._set_state(ResponseFuture.State.Futures)

        return self._call_status