Ejemplo n.º 1
0
class PauseTaskById(Resource):
    """
        This resource pauses job/task which can be resumed again
    """
    decorators = [require_oauth()]

    def post(self, _id):
        """
        Pause a task which is currently running.
        :param id: id of task
        :type _id: str
        :keyword user_id: user_id of tasks' owner
        :type user_id: int
        :rtype json

        :Example:
            headers = {'Authorization': 'Bearer <access_token>'}
            response = requests.post(API_URL + '/v1/tasks/5das76nbv950nghg8j8-33ddd3kfdw2/pause/', headers=headers)

        .. Response::
            {
               "message":"Task has been paused successfully"
            }

        .. Status:: 200 (OK)
                    404 (Task Not Found)
                    500 (Internal Server Error)

        .. Error code:: 6053(Task Already Paused)

        """
        # check and raise exception if job is already paused or not present
        user_id = request.user.id
        raise_if_scheduler_not_running()
        task = check_job_state(job_id=_id, job_state_to_check='paused')
        if task and task.args[0] == user_id:
            scheduler.pause_job(job_id=_id)
            return dict(message="Task has been successfully paused")
        raise ResourceNotFound(error_message="Task not found")
Ejemplo n.º 2
0
class AdminTasks(Resource):
    """
        This resource returns a list of tasks owned by a user or service by using pagination and it's accessible to
        admin users only.
    """
    decorators = [require_oauth()]

    # a parent class and put all the core pagination functionality in its get() and then we can later override that

    def get(self):
        """
        This action returns a list of apscheduler scheduled tasks.
        :return tasks_data: a dictionary containing list of tasks
        :rtype: json


        :Example (in case of pagination):
            By default, it will return 30 jobs (max)

            Case 1:

             >>> headers = {'Authorization': 'Bearer <access_token>'}
             >>> response = requests.get(API_URL + '/admin/v1/tasks?page=2', headers=headers)

            # Returns 30 jobs ranging from 30-59 ( zero-based index )

            Case 2:

             >>> headers = {'Authorization': 'Bearer <access_token>'}
             >>> response = requests.get(API_URL + '/admin/v1/tasks?page=2&per_page=35', headers=headers)

            # Returns 35 jobs ranging from 35-69 ( zero-based index )

        :Example:

        In case of task_category filter

             >>> headers = {'Authorization': 'Bearer <access_token>'}
             >>> response = requests.get(API_URL + '/admin/v1/tasks?task_category=general', headers=headers)

        In case of task_type filter

             >>> headers = {'Authorization': 'Bearer <access_token>'}
             >>> response = requests.get(API_URL + '/admin/v1/tasks?task_type=periodic', headers=headers)

        In case of jobs of a specific user

             >>> headers = {'Authorization': 'Bearer <access_token>'}
             >>> response = requests.get(API_URL + '/admin/v1/tasks?user_id=2', headers=headers)


        In case of paused or running jobs only

             >>> headers = {'Authorization': 'Bearer <access_token>'}
             # returns paused jobs only
             >>> response = requests.get(API_URL + '/admin/v1/tasks?paused=true', headers=headers)
             # returns running jobs only
             >>> response = requests.get(API_URL + '/admin/v1/tasks?paused=false', headers=headers)


        Response will be similar to get all tasks endpoint with few additional fields

        .. Response::

            {
                "tasks": [
                    {
                        "id": "5das76nbv950nghg8j8-33ddd3kfdw2",
                        "user_email": "*****@*****.**",
                        "task_type": "user",
                        "data":{
                            "url": "http://getTalent.com/sms/send/",
                            "request_method": "post",
                            "post_data": {
                                "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)
                    401 (Unauthorized Error)
                    500 (Internal Server Error)

        """

        # In case of higher number of scheduled task running for a particular user and user wants to get only
        # a limited number of jobs by specifying page and per_page parameter, then return only specified jobs

        # Default per_page size
        default_per_page = 30

        # If user didn't specify page or per_page, then it should default to 1 and 30 respectively.
        page, per_page = get_pagination_params(
            request, default_per_page=default_per_page)

        raise_if_scheduler_not_running()
        tasks = scheduler.get_jobs()

        # Get all param filters
        user_id = request.args.get('user_id')
        paused = request.args.get('paused')
        task_type = request.args.get('task_type')
        task_category = request.args.get('task_category')

        # If user_id is given then only return jobs of that particular user
        if user_id:
            if not (str(user_id).isdigit() and int(user_id) > 0):
                raise InvalidUsage("user_id should be of type int")
            tasks = filter(lambda _task: _task.args[0] == int(user_id), tasks)

        # If paused is given then only return paused jobs.
        if paused:
            tasks = filter_paused_jobs(tasks, is_paused=paused)

        # If task_type is specified then return only specified `one_time` or `periodic` jobs
        if task_type:
            tasks = filter_jobs_using_task_type(tasks, task_type=task_type)

        # If task_category is given then return only specified `user` or `general` job
        if task_category:
            tasks = filter_jobs_using_task_category(
                tasks, task_category=task_category)

        # The following case should never occur. As the general jobs are independent of user. So, if user use such
        # a filter then raise Invalid usage api exception.
        if user_id and task_category == SchedulerUtils.CATEGORY_GENERAL:
            raise InvalidUsage(
                error_message=
                "user and task_category cannot be used together. General jobs are independent of users."
            )

        tasks_count = len(tasks)

        # If page is 1, and per_page is 30 then task_indices will look like list of integers e.g [0-29]
        task_indices = range((page - 1) * per_page, page * per_page)

        tasks = [
            serialize_task_admin(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)
Ejemplo n.º 3
0
class PauseTasks(Resource):
    """
        This resource pauses jobs/tasks which can be resumed again
    """
    decorators = [require_oauth()]

    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)
Ejemplo n.º 4
0
class ResumeTasks(Resource):
    """
        This resource resumes a previously paused jobs/tasks
    """
    decorators = [require_oauth()]

    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)