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
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)
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)
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)
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)
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)
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")
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
def wrapper(*args, **kwargs): if not qapi.is_queue_server(): _fail(405, "Not a Queue Server") return func(*args, **kwargs)