def get_result_or_run_fql(task_cls, user_id, commit=True, stale_mins=15, *args, **kwargs): """ Look at the UserTask collection to see if there is already a task with the given age This returns an ASYNC RESULT! """ import ipdb ipdb.set_trace() task_name = '%s:%s' % (run_fql.name, task_cls().name) task_stale_time = datetime.datetime.utcnow() - datetime.timedelta(minutes=stale_mins) user = User.objects.get(id=user_id) tasks = UserTask.objects(user=user, task_name=task_name, created__gt=task_stale_time) if tasks: task = tasks[0] # Get the task id and return the state task_async = celery.AsyncResult(task.task_id) # Note that we can create an AsyncResult with ANY ID, no exception is thrown # A task with a made-up id is 'PENDING' # so we need to check if the result exists, if task_async.state != 'PENDING' or task_async.state != 'FAILED': # Return the async result so the child can decide whether to wait return task_async # Task doesn't exist, run it task_async = run_fql.delay(task_cls, user_id, commit, *args, **kwargs) return task_async
def get(self, fb_id, **kwargs): if not self.is_authorized(fb_id): abort(403) user = current_user._get_current_object() # We use the url to decide which Resource the user is targeting resource_url = request.path.rsplit("/progress", 1)[0] adapter = app.create_url_adapter(request) # match() only matches if the *request method* is correct # GET by default try: endpoint = adapter.match(resource_url)[0] except MethodNotAllowed: # Try POST try: endpoint = adapter.match(resource_url, method="POST")[0] except MethodNotAllowed: # Not GET or POST raise Exception( "Unable to resolve url <%s> to endpoint. " "Either URL is wrong or it doesn't support GET or POST" ) resource_class = app.view_functions[endpoint].view_class resource_instance = resource_class() # Some resources call different tasks based on URL task_name = resource_instance.get_depends_on_task_name(resource_url, **kwargs) if task_name is None: raise AttributeError("Can't get progress of a task without the attr `depends_on_task`") # Check the UserTask to get the latest task with that name # Cases: # - No matching UserTask # - UserTask matches # - UserTask matches but its old # task_stale_time = datetime.datetime.utcnow() - datetime.timedelta(minutes=TASK_STALE_MINS) tasks = UserTask.objects(user=user, task_name=task_name) if tasks: task = tasks[0] # Get the task id and return the state task_async = celery.AsyncResult(task.task_id) return {"task_id": task.task_id, "created": str(task.created), "state": task_async.state} else: # No tasks in DB, or they're old. Return a different status # app.logger.debug('User %s, looking for task %s, none found in db' % (user, task_name)) return {"task_id": "", "created": "", "state": "NOT_STARTED"}
def get_result_or_run_fql(task_cls, user_id, commit=True, stale_mins=15, *args, **kwargs): """ Look at the UserTask collection to see if there is already a task with the given age This returns an ASYNC RESULT! """ import ipdb ipdb.set_trace() task_name = '%s:%s' % (run_fql.name, task_cls().name) task_stale_time = datetime.datetime.utcnow() - datetime.timedelta( minutes=stale_mins) user = User.objects.get(id=user_id) tasks = UserTask.objects(user=user, task_name=task_name, created__gt=task_stale_time) if tasks: task = tasks[0] # Get the task id and return the state task_async = celery.AsyncResult(task.task_id) # Note that we can create an AsyncResult with ANY ID, no exception is thrown # A task with a made-up id is 'PENDING' # so we need to check if the result exists, if task_async.state != 'PENDING' or task_async.state != 'FAILED': # Return the async result so the child can decide whether to wait return task_async # Task doesn't exist, run it task_async = run_fql.delay(task_cls, user_id, commit, *args, **kwargs) return task_async
def log_task(self, async_result, user_id, log_name=None): user = User.objects.get(id=user_id) log_name = log_name or self.name ut = UserTask(user=user, task_name=log_name, task_id=async_result.id) ut.save()