예제 #1
0
def get_lock_if_job_is_runnable(app_name, job_id):
    """Return a lock instance or False.  If returning False,
    the job is not ready to execute.
    """

    available = qb.check_state(app_name,
                               job_id,
                               pending=True,
                               raise_if_not_exists=True)
    if not available:
        try:
            raise RuntimeError(
                "I found a job in queue that wasn't"
                " in state pending. This might be a code bug. You"
                " probably queued 2+ of the same job!")
        except RuntimeError as err:
            # force a traceback in the logs
            log.exception(err,
                          extra=dict(app_name=app_name,
                                     job_id=job_id,
                                     state=qb.check_state(app_name,
                                                          job_id,
                                                          _get=True)))
            return False
    l = qb.obtain_execute_lock(app_name, job_id, blocking=False)
    if l is False:
        log.warn(
            'Could not obtain execute lock for task because'
            ' something is already processing this job_id',
            extra=dict(app_name=app_name, job_id=job_id))
        return False
    return l
예제 #2
0
파일: runner.py 프로젝트: kszucs/stolos
def get_lock_if_job_is_runnable(app_name, job_id):
    """Return a lock instance or False.  If returning False,
    the job is not ready to execute.
    """

    available = qb.check_state(
        app_name, job_id, pending=True, raise_if_not_exists=True)
    if not available:
        try:
            raise RuntimeError(
                "I found a job in queue that wasn't"
                " in state pending. This might be a code bug. You"
                " probably queued 2+ of the same job!")
        except RuntimeError as err:
            # force a traceback in the logs
            log.exception(
                err, extra=dict(
                    app_name=app_name,
                    job_id=job_id,
                    state=qb.check_state(
                        app_name, job_id, _get=True)))
            return False
    l = qb.obtain_execute_lock(app_name, job_id, blocking=False)
    if l is False:
        log.warn('Could not obtain execute lock for task because'
                 ' something is already processing this job_id',
                 extra=dict(app_name=app_name, job_id=job_id))
        return False
    return l
예제 #3
0
def initialize(objects, args=None, parse_known_args=False,
               **argument_parser_kwargs):
    """
    Initialize Stolos such that we ensure all required configuration settings
    are unified in one central place before we do anything with Stolos.
    Raises error if any parsers define conflicting argument options.

    This function is called by user-facing or application-level code.
    All internal stolos libraries should call to stolos.get_NS() when they need
    to access configuration.  Internal libraries should not call this function.

    Returns (argparse.ArgumentParser(...), argparse.Namespace(...))

    `objects` - is a list of build_arg_parser functions or objects
        (ie Stolos modules) containing a callable build_arg_parser attribute.
    `args` - (optional).  Define command-line arguments to use.
        Default to sys.argv (which is what argparse does).
        Explicitly pass args=[] to not read command-line arguments, and instead
        expect that all arguments are passed in as environment variables.
        To guarantee NO arguments are read from sys.argv, set args=[]
        Example:  args=['--option1', 'val', ...]
    `parse_known_args` - if True, parse only known commandline arguments and
        do not add_help (ie don't recognize '-h').  Assume you will
        post-process the argument parser and add a --help option later.
        If False, add_help (ie recognize '-h') and fail if anything on
        command-line is not recognized by the argument parser
    `argument_parser_kwargs` - (optional) passed to the ArgumentParser(...)
    """
    # partially initialize a parser to get selected configuration backend
    parser = at.build_arg_parser(
        description="Initialize Stolos, whether running it or calling its api",
        parents=list(_get_parent_parsers(objects)),
        **argument_parser_kwargs)
    if args is not None:
        ns, _ = parser.parse_known_args(args)
    else:
        ns, _ = parser.parse_known_args()

    # get a new parser updated with options for each chosen backend
    parser = initialize_backend(
        ns.configuration_backend, parser, add_help=False)
    parser = initialize_backend(
        ns.queue_backend, parser, add_help=not bool(parse_known_args))

    if not parse_known_args:
        ns = parser.parse_args(args)
    else:
        ns, _ = parser.parse_known_args()
    stolos.NS = ns
    try:
        del stolos.Uninitialized
    except AttributeError:
        log.warn(
            "Stolos was re-initialized.  You may have imported the api and"
            " then done something weird like re-import it or manually"
            " call Stolos's initializer."
        )
    return parser, ns
예제 #4
0
파일: runner.py 프로젝트: kszucs/stolos
def _handle_failure(ns, q, lock):
    """The job has failed.  Increase it's retry limit, send to back of queue,
    and release the lock"""
    exceeded_retry_limit = qb.inc_retry_count(
        app_name=ns.app_name, job_id=ns.job_id, max_retry=ns.max_retry)
    if exceeded_retry_limit:
        q.consume()
    else:
        _send_to_back_of_queue(
            q=q, app_name=ns.app_name, job_id=ns.job_id)
    if lock:
        lock.release()
    log.warn("Job failed", extra=dict(
        job_id=ns.job_id, app_name=ns.app_name, failed=True))
예제 #5
0
def _handle_failure(ns, q, lock):
    """The job has failed.  Increase it's retry limit, send to back of queue,
    and release the lock"""
    exceeded_retry_limit = qb.inc_retry_count(app_name=ns.app_name,
                                              job_id=ns.job_id,
                                              max_retry=ns.max_retry)
    if exceeded_retry_limit:
        q.consume()
    else:
        _send_to_back_of_queue(q=q, app_name=ns.app_name, job_id=ns.job_id)
    if lock:
        lock.release()
    log.warn("Job failed",
             extra=dict(job_id=ns.job_id, app_name=ns.app_name, failed=True))
예제 #6
0
파일: runner.py 프로젝트: kszucs/stolos
def _handle_manually_given_job_id(ns):
    """This process was given a specific --job_id arg.
    Decide whether it's okay to execute this job_id,
    and if its okay to go forward, set job_id state appropriately
    """
    log.warn(
        ('using specific job_id and'
         ' blindly assuming this job is not already queued.'),
        extra=dict(app_name=ns.app_name, job_id=ns.job_id))
    if qb.get_qbclient().exists(qb.get_job_path(ns.app_name, ns.job_id)):
        msg = ('Will not execute this task because it might be already'
               ' queued or completed!')
        log.critical(
            msg, extra=dict(app_name=ns.app_name, job_id=ns.job_id))
        raise UserWarning(msg)
    lock = qb.obtain_execute_lock(
        ns.app_name, ns.job_id, safe=False, raise_on_error=True,
        blocking=False)
    qb.set_state(ns.app_name, ns.job_id, pending=True)
    return lock
예제 #7
0
def _handle_manually_given_job_id(ns):
    """This process was given a specific --job_id arg.
    Decide whether it's okay to execute this job_id,
    and if its okay to go forward, set job_id state appropriately
    """
    log.warn(('using specific job_id and'
              ' blindly assuming this job is not already queued.'),
             extra=dict(app_name=ns.app_name, job_id=ns.job_id))
    if qb.get_qbclient().exists(qb.get_job_path(ns.app_name, ns.job_id)):
        msg = ('Will not execute this task because it might be already'
               ' queued or completed!')
        log.critical(msg, extra=dict(app_name=ns.app_name, job_id=ns.job_id))
        raise UserWarning(msg)
    lock = qb.obtain_execute_lock(ns.app_name,
                                  ns.job_id,
                                  safe=False,
                                  raise_on_error=True,
                                  blocking=False)
    qb.set_state(ns.app_name, ns.job_id, pending=True)
    return lock
예제 #8
0
파일: initializer.py 프로젝트: xyuan/stolos
def initialize(objects,
               args=None,
               parse_known_args=False,
               **argument_parser_kwargs):
    """
    Initialize Stolos such that we ensure all required configuration settings
    are unified in one central place before we do anything with Stolos.
    Raises error if any parsers define conflicting argument options.

    This function is called by user-facing or application-level code.
    All internal stolos libraries should call to stolos.get_NS() when they need
    to access configuration.  Internal libraries should not call this function.

    Returns (argparse.ArgumentParser(...), argparse.Namespace(...))

    `objects` - is a list of build_arg_parser functions or objects
        (ie Stolos modules) containing a callable build_arg_parser attribute.
    `args` - (optional).  Define command-line arguments to use.
        Default to sys.argv (which is what argparse does).
        Explicitly pass args=[] to not read command-line arguments, and instead
        expect that all arguments are passed in as environment variables.
        To guarantee NO arguments are read from sys.argv, set args=[]
        Example:  args=['--option1', 'val', ...]
    `parse_known_args` - if True, parse only known commandline arguments and
        do not add_help (ie don't recognize '-h').  Assume you will
        post-process the argument parser and add a --help option later.
        If False, add_help (ie recognize '-h') and fail if anything on
        command-line is not recognized by the argument parser
    `argument_parser_kwargs` - (optional) passed to the ArgumentParser(...)
    """
    # partially initialize a parser to get selected configuration backend
    parser = at.build_arg_parser(
        description="Initialize Stolos, whether running it or calling its api",
        parents=list(_get_parent_parsers(objects)),
        **argument_parser_kwargs)
    if args is not None:
        ns, _ = parser.parse_known_args(args)
    else:
        ns, _ = parser.parse_known_args()

    # get a new parser updated with options for each chosen backend
    parser = initialize_backend(ns.configuration_backend,
                                parser,
                                add_help=False)
    parser = initialize_backend(ns.queue_backend,
                                parser,
                                add_help=not bool(parse_known_args))

    if not parse_known_args:
        ns = parser.parse_args(args)
    else:
        ns, _ = parser.parse_known_args()
    stolos.NS = ns
    try:
        del stolos.Uninitialized
    except AttributeError:
        log.warn(
            "Stolos was re-initialized.  You may have imported the api and"
            " then done something weird like re-import it or manually"
            " call Stolos's initializer.")
    return parser, ns