def test__shoveller(self, easy_job_mock, produce_to_queue_mock):
        job_mock = Mock()
        job_mock.tag = "unknown"
        easy_job_mock.create_from_dict.return_value = job_mock
        body = json.dumps({"body": "work body"})
        message = Mock()
        api = "http://test.api.com/test_dest"
        api_request_headers = {"title": "Yippi"}
        job = EasyJob.create(api, constants.API_REMOTE, api_request_headers=api_request_headers)
        headers = {}
        headers.update(job.to_dict())
        message.headers = headers

        self.retry_consumer._shoveller(body, message)

        produce_to_queue_mock.assert_called_with(constants.BUFFER_QUEUE, body, job_mock)
    def test__push_msg_to_dlq(self, easy_job_mock, produce_to_queue):
        job_mock = Mock()
        job_mock.tag = "unknown"
        job_mock.no_of_retries = 1
        easy_job_mock.create_from_dict.return_value = job_mock

        body = {"body": "work body"}
        message = Mock()
        api_request_headers = {"title": "Yippi"}
        job = EasyJob.create("test_api",
                             constants.API_REMOTE,
                             api_request_headers=api_request_headers)
        headers = {}
        headers.update(job.to_dict())
        message.headers = headers

        self.work_queue_con._push_msg_to_dlq(body, message, job)

        produce_to_queue.assert_called_with(constants.DEAD_LETTER_QUEUE, body,
                                            job)
    def test_process_message(self, easy_job_mock, produce_to_queue_mock):
        # mock the job to be created in the process_message call
        job_mock = Mock()
        job_mock.tag = "unknown"
        job_mock.no_of_retries = 1
        easy_job_mock.create_from_dict.return_value = job_mock

        body = json.dumps({"body": "work body"})
        message = Mock()
        api = "http://test.api.com/test_dest"
        api_request_headers = {"title": "Yippi"}
        job = EasyJob.create(api, constants.API_REMOTE, api_request_headers=api_request_headers)
        headers = {}
        headers.update(job.to_dict())
        message.headers = headers

        # when no of retires is less than max then add back to work queue
        self.retry_consumer.process_message(body, message)
        produce_to_queue_mock.assert_called_with(constants.WORK_QUEUE, body, job_mock)
        message.ack.assert_called()
        message.reset_mock()

        # test exception
        produce_to_queue_mock.side_effect = Exception()
        self.retry_consumer.process_message(body, message)
        message.assert_not_called()

        message.reset_mock()

        # when no of retries is more than max retries then add to dead letter queue
        produce_to_queue_mock.side_effect = None
        job_mock.no_of_retries = constants.DEFAULT_MAX_JOB_RETRIES + 1
        self.retry_consumer.process_message(body, message)
        produce_to_queue_mock.assert_called_with(constants.DEAD_LETTER_QUEUE, body, job_mock)
        message.ack.assert_called()

        # test exception
        message.reset_mock()
        produce_to_queue_mock.side_effect = Exception()
        self.retry_consumer.process_message(body, message)
        message.assert_not_called()
Example #4
0
    def enqueue_job(self,
                    api,
                    type,
                    tag=None,
                    remote_call_type=None,
                    data=None,
                    api_request_headers=None,
                    content_type=None,
                    notification_handler=None):
        """
        Enqueue a job to be processed.
        :param api: The api to be called when job is run
        :param type: The type of job (Remote/Local) when local then a python call is made and in remote an REST call is made.
        :param tag: a tag for the job to be run
        :param remote_call_type: is the call POST/GET/PUT
        :param data: a data payload to be passed along in the job
        :param api_request_headers: request headers to be passed along in a remote call
        :param content_type: content type to be used in remote call
        :param notification_handler: the api to be called when a job goes into dlq (type same as api)
        :return: A unique job id assigned to the job.
        """
        self.validate_init()

        # create the job
        job = EasyJob.create(api,
                             type,
                             tag=tag,
                             remote_call_type=remote_call_type,
                             data=data,
                             api_request_headers=api_request_headers,
                             content_type=content_type,
                             notification_handler=notification_handler)

        # enqueue
        enqueue(self._producer, constants.WORK_QUEUE, job, data)

        return job.id
    def test_process_message(self, remote_call_type_mock, push_dlq_mock,
                             push_retry_mock):
        post = Mock()
        response = Mock()
        response.status_code = 200
        post.return_value = response
        remote_call_type_mock.get.return_value = post

        # Test remote job flow
        body = json.dumps({"body": "work body"})
        message = Mock()
        api = "http://test.api.com/test_dest"
        api_request_headers = {"title": "Yippi"}
        job = EasyJob.create(api,
                             constants.API_REMOTE,
                             api_request_headers=api_request_headers)
        headers = {}
        headers.update(job.to_dict())
        message.headers = headers

        self.work_queue_con.process_message(body, message)

        data_body = {'tag': 'unknown', 'data': body, 'job_id': job.id}

        # when return in 200
        post.assert_called_with(api,
                                data=data_body,
                                timeout=constants.DEFAULT_ASYNC_TIMEOUT,
                                headers=api_request_headers)

        # when the status code is 410 (in the error list to be reported
        # then the job will be added to be dlq
        response.status_code = 410
        response.text = "big error"
        self.work_queue_con.process_message(body, message)
        push_dlq_mock.assert_called()

        # when the status code is 5XX then add to the error queue
        response.status_code = 520
        response.text = "big error"
        self.work_queue_con.process_message(body, message)
        push_retry_mock.assert_called()

        # test local flow

        sys.path += os.path.dirname(test_class.__file__)

        # test with module function
        api = test_class.dummy_function_external
        job = EasyJob.create(api, constants.API_LOCAL)

        headers = {}
        headers.update(job.to_dict())
        message.headers = headers
        test_class.TestClass.module_function_called = False
        self.work_queue_con.process_message(body, message)
        self.assertEqual(test_class.TestClass.module_function_called, True)

        # test with string function
        api = "tests.test_class.dummy_function_external"
        job = EasyJob.create(api, constants.API_LOCAL)

        headers = {}
        headers.update(job.to_dict())
        message.headers = headers
        test_class.TestClass.module_function_called = False
        self.work_queue_con.process_message(body, message)
        self.assertEqual(test_class.TestClass.module_function_called, True)

        # test with instance function
        test_cls = test_class.TestClass()
        api = test_cls.dummy_function_in_class
        job = EasyJob.create(api, constants.API_LOCAL)

        headers = {}
        headers.update(job.to_dict())
        message.headers = headers
        test_class.TestClass.class_function_called = False
        self.work_queue_con.process_message(body, message)
        self.assertEqual(test_class.TestClass.class_function_called, True)

        # test with instance class
        tst_class = test_class.TestClass()
        job = EasyJob.create(tst_class, constants.API_LOCAL)

        headers = {}
        headers.update(job.to_dict())
        message.headers = headers
        test_class.TestClass.class_instance_called = False
        self.work_queue_con.process_message(body, message)
        self.assertEqual(test_class.TestClass.class_instance_called, True)