def post(self): """ Resume a previously paused tasks/jobs :param id: id of task :type id: str :keyword user_id: user_id of tasks' owner :type user_id: int :rtype json :Example: task_ids = { 'ids': [fasdff12n22m2jnr5n6skf,ascv3h5k1j43k6k8k32k345jmn,123n23n4n43m2kkcj53vdsxc] } headers = {'Authorization': 'Bearer <access_token>', 'Content-Type' : 'application/json'} response = requests.post(API_URL + '/v1/tasks/resume/', headers=headers, data=json.dumps(task_ids)) .. Response:: { "message":"Tasks have been resumed successfully" } .. Status:: 200 (OK) 207 (Not all paused) 404 (Bad Request) 500 (Internal Server Error) """ user_id = request.user.id raise_if_scheduler_not_running() try: req_data = request.get_json() except Exception: raise InvalidUsage("Bad Request, data should be in JSON") task_ids = req_data['ids'] if 'ids' in req_data and isinstance( req_data['ids'], list) else None if not task_ids: raise InvalidUsage("Bad Request, No data in ids", error_code=400) # Filter jobs that are not None valid_tasks = [ task for task in task_ids if scheduler.get_job(job_id=task) ] if valid_tasks: # Only keep jobs that belonged to the auth user valid_tasks = filter( lambda task_id: scheduler.get_job(job_id=task_id).args[0] == user_id, valid_tasks) # Resume each job for _id in valid_tasks: scheduler.resume_job(job_id=_id) if len(valid_tasks) != len(task_ids): none_tasks = filter( lambda task_id: scheduler.get_job(job_id=task_id) is None, task_ids) return dict(message='Unable to resume %s tasks' % len(none_tasks), paused=valid_tasks, not_found=none_tasks), 207 return dict(message="Tasks have been successfully resumed") raise InvalidUsage('Bad request, invalid data in request', error_code=400)
def post(self): """ Pause tasks which are currently running. :keyword user_id: user_id of tasks' owner :type user_id: int :rtype json :Example: task_ids = { 'ids': [fasdff12n22m2jnr5n6skf,ascv3h5k1j43k6k8k32k345jmn,123n23n4n43m2kkcj53vdsxc] } headers = {'Authorization': 'Bearer <access_token>', 'Content-Type' : 'application/json'} response = requests.post(API_URL + '/v1/tasks/pause/', headers=headers, data=json.dumps(task_ids)) .. Response:: { "message":"Tasks have been paused successfully" } .. Status:: 200 (OK) 400 (Bad Request) 207 (Not all Paused) 500 (Internal Server Error) """ user_id = request.user.id raise_if_scheduler_not_running() try: req_data = request.get_json() except Exception: raise InvalidUsage("Bad Request, data should be in json") task_ids = req_data['ids'] if 'ids' in req_data and isinstance( req_data['ids'], list) else None if not task_ids: raise InvalidUsage("Bad request, No data in ids", error_code=400) # Filter tasks which are None and of the current user valid_tasks = filter( lambda task_id: scheduler.get_job(job_id=task_id) and scheduler. get_job(job_id=task_id).args[0] == user_id, task_ids) if valid_tasks: for _id in valid_tasks: scheduler.pause_job(job_id=_id) if len(valid_tasks) != len(task_ids): none_tasks = filter( lambda task_id: scheduler.get_job(job_id=task_id) is None, task_ids) return dict(message='Unable to pause %s tasks' % len(none_tasks), paused=valid_tasks, not_found=none_tasks), 207 return dict(message="Tasks have been successfully paused") raise InvalidUsage('Bad request, invalid data in request', error_code=400)
def check_job_state(job_id, job_state_to_check): """ We retrieve a job and if it's pending we raise an error. If job_state_to_check is 'paused' and job's next_run_time is None then we raise an error indicating job is already in paused state. Likewise, if job_state_to_check is 'running' and next_run_time is not None then we raise an error indicating job is already running. :param job_id: job_id of task which is in APScheduler :param job_state_to_check: the state to check, if doesn't meet requirement then raise exception. 'func' can be 'running' or 'paused'. :return: """ # get job from scheduler by job_id job = scheduler.get_job(job_id=job_id) if not job: raise NotFoundError("Task with id '%s' not found." % job_id) # if job is pending then throw pending state exception if job.pending: raise PendingJobError("Task with id '%s' is in pending state. Scheduler not running" % job_id) # if job has next_run_datetime none, then job is in paused state if not job.next_run_time and job_state_to_check == 'paused': raise JobAlreadyPausedError("Task with id '%s' is already in paused state" % job_id) # if job has_next_run_datetime is not None, then job is in running state if job.next_run_time and job_state_to_check == 'running': raise JobAlreadyRunningError("Task with id '%s' is already in running state" % job_id) return job
def delete(self, _name): """ Deletes/removes a tasks from scheduler jobstore :param _name: name of general task :type _name: str :return: :Example: In case of SECRET_KEY headers = {'Authorization': 'Bearer <access_token>', 'X-Talent-Server-Key-ID': '<secret_key>'} response = requests.delete(API_URL + '/v1/tasks/name/custom_task', headers=headers) .. Response:: { 'message': 'Task has been removed successfully' } .. Status:: 200 (Resource deleted) 404 (Task Not found) 500 (Internal Server Error) """ user_id = request.user.id if request.user else None raise_if_scheduler_not_running() task_id = get_general_job_id(_name) task = scheduler.get_job(task_id) # Check if task is valid and belongs to the logged-in user if task and user_id is None and user_id == task.args[0]: scheduler_remove_job(task.id) return dict(message="Task has been removed successfully") raise ResourceNotFound(error_message="Task with name %s not found" % _name)
def delete(self, _id): """ Deletes/removes a tasks from scheduler store :param kwargs: :param _id: job_id :return: :Example: In case of authenticated user headers = {'Authorization': 'Bearer <access_token>'} response = requests.delete(API_URL + '/v1/tasks/id/5das76nbv950nghg8j8-33ddd3kfdw2', headers=headers) In case of SECRET_KEY headers = {'Authorization': 'Bearer <access_token>', 'X-Talent-Server-Key-ID': '<secret_key>'} response = requests.delete(API_URL + '/v1/tasks/id/5das76nbv950nghg8j8-33ddd3kfdw2', headers=headers) .. Response:: { 'message': 'Task has been removed successfully' } .. Status:: 200 (Resource deleted) 404 (Task Not found) 500 (Internal Server Error) """ user_id = request.user.id if request.user else None raise_if_scheduler_not_running() task = scheduler.get_job(_id) # Check if task is valid and belongs to the logged-in user if task and task.args[0] == user_id: scheduler_remove_job(task.id) logger.info('Job with id %s removed successfully.' % _id) return dict(message="Task has been removed successfully") raise ResourceNotFound(error_message="Task not found")
def get(self, _id): """ This action returns a task owned by a this user :param _id: id of task :type id: str :keyword user_id: user_id of tasks' owner :type user_id: int :return task: a dictionary containing a task data :rtype json :Example: In case of authenticated user headers = {'Authorization': 'Bearer <access_token>'} response = requests.get(API_URL + '/v1/tasks/id/5das76nbv950nghg8j8-33ddd3kfdw2', headers=headers) In case of SECRET_KEY headers = {'Authorization': 'Bearer <access_token>', 'X-Talent-Server-Key-ID': '<secret_key>'} response = requests.get(API_URL + '/v1/tasks/id/5das76nbv950nghg8j8-33ddd3kfdw2', headers=headers) .. Response:: { for one time schedule "task": { { "id": "5das76nbv950nghg8j8-33ddd3kfdw2", "url": "http://getTalent.com/sms/send/", "post_data": { "campaign_name": "SMS Campaign", "phone_number": "09230862348", "smart_list_id": 123456, "content": "text to be sent as sms" "some_other_kwarg": "abc" }, "frequency": 3601, "start_datetime": "2015-11-05T08:00:00", "end_datetime": "2015-12-05T08:00:00" "next_run_datetime": "2015-11-05T08:20:30", "task_type": "periodic" } } for interval schedule "task": { { "id": "5das76nbv950nghg8j8-33ddd3kfdw2", "url": "http://getTalent.com/email/send/", "post_data": { "campaign_name": "Email Campaign", "phone_number": "09230862348", "smart_list_id": 123456, "content": "text to be sent as Email" "some_other_kwarg": "abc" }, "run_datetime": "2015-11-05T08:00:00", "task_type": "one_time" } } .. Status:: 200 (OK) 404 (Task not found) 500 (Internal Server Error) """ user_id = request.user.id if request.user else None raise_if_scheduler_not_running() task = scheduler.get_job(_id) if task: task_owner_id = task.args[0] is_same_domain = user_id and User.get_by_id( task_owner_id).domain_id == request.user.domain_id # Make sure task is valid and belongs to logged-in user or user which is in same domain as requesting user is_owner = task_owner_id == user_id if is_owner or is_same_domain: task = serialize_task(task) if task: return dict(task=task) raise ResourceNotFound(error_message="Task not found")
def get(self): """ This action returns a list of user tasks and their count :return tasks_data: a dictionary containing list of tasks and their count :rtype json :Example (in case of pagination): By default, it will return 10 jobs (max) Case 1: headers = {'Authorization': 'Bearer <access_token>'} response = requests.get(API_URL + '/v1/tasks?page=3', headers=headers) # Returns 10 jobs ranging from 30-39 Case 2: headers = {'Authorization': 'Bearer <access_token>'} response = requests.get(API_URL + '/v1/tasks?page=5&per_page=12', headers=headers) # Returns 12 jobs ranging from 48-59 :Example: In case of authenticated user headers = {'Authorization': 'Bearer <access_token>'} response = requests.get(API_URL + '/v1/tasks/', headers=headers) In case of SECRET_KEY headers = {'Authorization': 'Bearer <access_token>', 'X-Talent-Server-Key-ID': '<secret_key>'} response = requests.get(API_URL + '/v1/tasks/', headers=headers) .. Response:: { "tasks": [ { "id": "5das76nbv950nghg8j8-33ddd3kfdw2", "post_data": { "url": "http://getTalent.com/sms/send/", "phone_number": "09230862348", "smart_list_id": 123456, "content": "text to be sent as sms" "some_other_kwarg": "abc", "campaign_name": "SMS Campaign" }, "frequency": 3601, # in seconds "start_datetime": "2015-11-05T08:00:00", "end_datetime": "2015-12-05T08:00:00" "next_run_datetime": "2015-11-05T08:20:30", "task_type": "periodic" } ] } .. Status:: 200 (OK) 400 (Invalid Usage) 500 (Internal Server Error) """ # In case of higher number of scheduled task running for a particular user and user want to get only # a limited number of jobs by specifying page and per_page parameter, then return only specified jobs page, per_page = get_pagination_params(request) user_id = request.user.id if request.user else None raise_if_scheduler_not_running() if user_id: task_ids = get_user_job_ids(user_id=user_id) else: task_ids = get_all_general_job_ids() tasks = [scheduler.get_job(task_id) for task_id in task_ids] tasks_count = len(tasks) # If page is 1, and per_page is 10 then task_indices will look like list of integers e.g [0-9] task_indices = range((page - 1) * per_page, page * per_page) tasks = [ serialize_task(tasks[index]) for index in task_indices if index < tasks_count and tasks[index] ] tasks = [task for task in tasks if task] header = generate_pagination_headers(tasks_count, per_page, page) return ApiResponse(response=dict(tasks=tasks), headers=header)
def get(self, _name): """ This action returns a task owned by other service :param _name: name of task :type _name: str :return task: a dictionary containing a task data :rtype json :Example: In case of SECRET_KEY headers = {'Authorization': 'Bearer <access_token>', 'X-Talent-Server-Key-ID': '<secret_key>'} response = requests.get(API_URL + '/v1/tasks/name/custom_task', headers=headers) .. Response:: { for one time scheduled task "task": { { "task_name": "custom_task", "id": "5das76nbv950nghg8j8-33ddd3kfdw2", "url": "http://getTalent.com/sms/send/", "post_data": { "campaign_name": "SMS Campaign", "phone_number": "09230862348", "smart_list_id": 123456, "content": "text to be sent as sms" "some_other_kwarg": "abc" }, "frequency": 3601, "start_datetime": "2015-11-05T08:00:00", "end_datetime": "2015-12-05T08:00:00" "next_run_datetime": "2015-11-05T08:20:30", "task_type": "periodic" } } for interval scheduled task "task": { { "task_name": "custom_task", "id": "5das76nbv950nghg8j8-33ddd3kfdw2", "url": "http://getTalent.com/email/send/", "post_data": { "campaign_name": "Email Campaign", "phone_number": "09230862348", "smart_list_id": 123456, "content": "text to be sent as Email" "some_other_kwarg": "abc" }, "run_datetime": "2015-11-05T08:00:00", "task_type": "one_time" } } .. Status:: 200 (OK) 404 (Task not found) 500 (Internal Server Error) """ user_id = request.user.id if request.user else None raise_if_scheduler_not_running() task_id = get_general_job_id(_name) task = scheduler.get_job(task_id) # Make sure task is valid and belongs to non-logged-in user # task.arg[0] contains user_id and if it is none then it is a general job if task and not user_id and not task.args[0]: task = serialize_task(task) if task: return dict(task=task) raise ResourceNotFound(error_message="Task with name %s not found" % _name)