예제 #1
0
def get_task(task_uid):
    """Resolves the task for the given task uid
    """
    if not api.is_uid(task_uid) or task_uid == "0":
        # 400 Bad Request, wrong task uid
        _fail(412, "Task uid empty or no valid format")

    task = qapi.get_queue().get_task(task_uid)
    if not task:
        _fail(404, "Task {}".format(task_uid))

    return task
예제 #2
0
def pop(context, request):  # noqa
    """Pops the next task from the queue, if any. Popped task is no longer
    available in the queued tasks pool, but added in the running tasks pool
    """
    # Get the consumer ID
    consumer_id = req.get_json().get("consumer_id")
    if not is_consumer_id(consumer_id):
        _fail(428, "No valid consumer id")

    # Pop the task from the queue
    task = qapi.get_queue().pop(consumer_id)

    # Return the task info
    task_uid = get_task_uid(task, default="<empty>")
    logger.info("::server.pop: {} [{}]".format(task_uid, consumer_id))
    return get_task_info(task, complete=True)
예제 #3
0
def add(context, request):  # noqa
    """Adds a new task to the queue server
    """
    # Extract the task(s) from the request
    raw_tasks = req.get_request_data()

    # Convert raw task(s) to QueueTask object(s)
    items = map(to_task, raw_tasks)
    valid = map(is_task, items)
    if not all(valid):
        _fail(406, "No valid task(s)")

    # Add the task(s) to the queue
    map(qapi.get_queue().add, items)

    # Return the process summary
    return get_tasks_summary(items, "server.add", complete=False)
예제 #4
0
def timeout(context, request):  # noqa
    """The task timed out
    """
    # Get the task uid
    request_data = req.get_json()
    task_uid = request_data.get("task_uid")

    # Get the task
    task = get_task(task_uid)
    if task.status not in [
            "running",
    ]:
        _fail(412, "Task is not running")

    # Notify the queue
    qapi.get_queue().timeout(task)

    # Return the process summary
    task_info = {"task": get_task_info(task)}
    return get_message_summary(task_uid, "server.timeout", **task_info)
예제 #5
0
def done(context, request):  # noqa
    """Acknowledge the task has been successfully processed. Task is removed
    from the running tasks pool and returned
    """
    # Get the task uid
    task_uid = req.get_json().get("task_uid")

    # Get the task
    task = get_task(task_uid)
    if task.status not in [
            "running",
    ]:
        _fail(412, "Task is not running")

    # Notify the queue
    qapi.get_queue().done(task)

    # Return the process summary
    msg = "Task done: {}".format(task_uid)
    task_info = {"task": get_task_info(task)}
    return get_message_summary(msg, "server.done", **task_info)
예제 #6
0
def fail(context, request):  # noqa
    """Acknowledge the task has NOT been successfully processed. Task is
    moved from running tasks to failed or re-queued and returned
    """
    # Get the task uid
    request_data = req.get_json()
    task_uid = request_data.get("task_uid")
    error_message = request_data.get("error_message")

    # Get the task
    task = get_task(task_uid)
    if task.status not in [
            "running",
    ]:
        _fail(412, "Task is not running")

    # Notify the queue
    qapi.get_queue().fail(task, error_message=error_message)

    # Return the process summary
    msg = "Task failed: {}".format(task_uid)
    task_info = {"task": get_task_info(task)}
    return get_message_summary(msg, "server.fail", **task_info)
예제 #7
0
def process(context, request, task_uid=None):  # noqa
    """Processes the task passed-in
    """
    # disable CSRF
    req.disable_csrf_protection()

    # Maybe the task uid has been sent via POST
    task_uid = task_uid or req.get_json().get("task_uid")

    # Get the task
    task = get_task(task_uid)
    if task.username != capi.get_current_user().id:
        # 403 Authenticated, but user does not have access to the resource
        _fail(403)

    # Process
    t0 = time.time()
    task_context = task.get_context()
    if not task_context:
        _fail(500, "Task's context is not available")

    # Get the adapter able to process this specific type of task
    adapter = queryAdapter(task_context, IQueuedTaskAdapter, name=task.name)
    if not adapter:
        _fail(501, "No adapter found for {}".format(task.name))

    logger.info("Processing task {}: '{}' for '{}' ({}) ...".format(
        task.task_short_uid, task.name, capi.get_id(task_context),
        task.context_uid))

    # Inject the queue_consumer marker to the request so guards skip checks
    # against the queue
    request = capi.get_request()
    request.set("queue_tuid", task_uid)

    # If the task refers to a worksheet, inject (ws_id) in params to make
    # sure guards (assign, un-assign) return True
    if IWorksheet.providedBy(task_context):
        request.set("ws_uid", capi.get_uid(task_context))

    # Process the task
    adapter.process(task)

    # Sleep a bit for minimum effect against userland threads
    # Better to have a transaction conflict here than in userland
    min_seconds = task.get("min_seconds", 3)
    while time.time() - t0 < min_seconds:
        time.sleep(0.5)

    msg = "Processed: {}".format(task.task_short_uid)
    return get_message_summary(msg, "consumer.process")
예제 #8
0
def get_task(task_uid):
    """Resolves the task for the given task uid
    """
    if not capi.is_uid(task_uid) or task_uid == "0":
        # 400 Bad Request, wrong task uid
        _fail(412, "Task uid empty or no valid format")

    task = api.get_queue().get_task(task_uid)
    if not task:
        _fail(404, "Task {}".format(task_uid))

    if not capi.is_uid(task.context_uid):
        _fail(500, "Task's context uid is not valid")

    return task
예제 #9
0
 def wrapper(*args, **kwargs):
     if not qapi.is_queue_server():
         _fail(405, "Not a Queue Server")
     return func(*args, **kwargs)