def test_execute_task_raises_exception_if_engine_returns_http_status_other_than_no_content_204(self):
        client = ExternalTaskClient(worker_id=1)
        task = ExternalTask({"id": "1", "topicName": "my_topic"})
        executor = ExternalTaskExecutor(worker_id=1, external_task_client=client)

        TaskResultStatusInput = collections.namedtuple('TaskResultStatusInput',
                                                       ['task_status', 'task_action', 'task_status_url',
                                                        'http_status_code', 'expected_error_message'])

        task_result_tests = [
            TaskResultStatusInput("complete", self.task_success_action,
                                  client.get_task_complete_url(task.get_task_id()), HTTPStatus.OK,
                                  'Not able to mark complete for task_id=1 for topic=my_topic, worker_id=1'),
            TaskResultStatusInput("failure", self.task_failure_action,
                                  client.get_task_failure_url(task.get_task_id()), HTTPStatus.CREATED,
                                  'Not able to mark failure for task_id=1 for topic=my_topic, worker_id=1'),
            TaskResultStatusInput("bpmn_error", self.task_bpmn_error_action,
                                  client.get_task_bpmn_error_url(task.get_task_id()), HTTPStatus.ACCEPTED,
                                  'Not able to mark BPMN Error for task_id=1 for topic=my_topic, worker_id=1')
        ]

        for task_result_test in task_result_tests:
            with self.subTest(task_result_test.task_status):
                responses.add(responses.POST, task_result_test.task_status_url,
                              status=task_result_test.http_status_code)

                with self.assertRaises(Exception) as exception_ctx:
                    executor.execute_task(task, task_result_test.task_action)

                self.assertEqual(task_result_test.expected_error_message, str(exception_ctx.exception))
    def test_execute_task_raises_exception_raised_when_updating_status_in_engine(self):
        client = ExternalTaskClient(worker_id=1)
        task = ExternalTask({"id": "1", "topicName": "my_topic"})
        executor = ExternalTaskExecutor(worker_id=1, external_task_client=client)

        TaskResultStatusInput = collections.namedtuple('TaskResultStatusInput',
                                                       ['task_status', 'task_action', 'task_status_url',
                                                        'error_message'])

        task_result_tests = [
            TaskResultStatusInput("complete", self.task_success_action,
                                  client.get_task_complete_url(task.get_task_id()),
                                  "cannot update task status to complete"),
            TaskResultStatusInput("failure", self.task_failure_action,
                                  client.get_task_failure_url(task.get_task_id()),
                                  "cannot update task status to failure"),
            TaskResultStatusInput("bpmn_error", self.task_bpmn_error_action,
                                  client.get_task_bpmn_error_url(task.get_task_id()),
                                  "cannot update task status to BPMN err")
        ]

        for task_result_test in task_result_tests:
            with self.subTest(task_result_test.task_status):
                responses.add(responses.POST, task_result_test.task_status_url,
                              body=Exception(task_result_test.error_message))

                with self.assertRaises(Exception) as exception_ctx:
                    executor.execute_task(task, task_result_test.task_action)

                self.assertEqual(task_result_test.error_message, str(exception_ctx.exception))
Example #3
0
 def __init__(self, worker_id, base_url=ENGINE_LOCAL_BASE_URL, config=None):
     config = config if config is not None else {
     }  # To avoid to have a mutable default for a parameter
     self.worker_id = worker_id
     self.client = ExternalTaskClient(self.worker_id, base_url, config)
     self.executor = ExternalTaskExecutor(self.worker_id, self.client)
     self.config = config
     self._log_with_context(
         f"Created new External Task Worker with config: {self.config}")
    def test_task_result_not_complete_failure_bpmnerror_raises_exception(self):
        task = ExternalTask({"id": "1", "topicName": "my_topic"})
        external_task_client = ExternalTaskClient(worker_id=1)
        executor = ExternalTaskExecutor(worker_id=1, external_task_client=external_task_client)

        with self.assertRaises(Exception) as exception_ctx:
            executor.execute_task(task, self.task_result_not_complete_failure_bpmnerror)

        self.assertEqual("task result for task_id=1 must be either complete/failure/BPMNError",
                         str(exception_ctx.exception))
    def test_task_bpmn_error(self):
        task = ExternalTask({"id": "1", "topicName": "my_topic"})
        expected_task_result = TaskResult.bpmn_error(task, error_code="bpmn_err_code_1", error_message="bpmn error")

        external_task_client = ExternalTaskClient(worker_id=1)
        responses.add(responses.POST, external_task_client.get_task_bpmn_error_url(task.get_task_id()),
                      status=HTTPStatus.NO_CONTENT)
        executor = ExternalTaskExecutor(worker_id=1, external_task_client=external_task_client)

        actual_task_result = executor.execute_task(task, self.task_bpmn_error_action)
        self.assertEqual(str(expected_task_result), str(actual_task_result))
    def test_task_complete(self):
        task = ExternalTask({"id": "1", "topicName": "my_topic"})
        output_vars = {"var1": 1, "var2": "value", "var3": True}
        expected_task_result = TaskResult.success(task, output_vars)

        external_task_client = ExternalTaskClient(worker_id=1)
        responses.add(responses.POST, external_task_client.get_task_complete_url(task.get_task_id()),
                      status=HTTPStatus.NO_CONTENT)
        executor = ExternalTaskExecutor(worker_id=1, external_task_client=external_task_client)

        actual_task_result = executor.execute_task(task, self.task_success_action)
        self.assertEqual(str(expected_task_result), str(actual_task_result))
    def test_task_failure(self):
        task = ExternalTask({"id": "1", "topicName": "my_topic"})
        expected_task_result = TaskResult.failure(task,
                                                  error_message="unknown task failure", error_details="unknown error",
                                                  retries=3, retry_timeout=30000)

        external_task_client = ExternalTaskClient(worker_id=1)
        responses.add(responses.POST, external_task_client.get_task_failure_url(task.get_task_id()),
                      status=HTTPStatus.NO_CONTENT)
        executor = ExternalTaskExecutor(worker_id=1, external_task_client=external_task_client)

        actual_task_result = executor.execute_task(task, self.task_failure_action)
        self.assertEqual(str(expected_task_result), str(actual_task_result))
Example #8
0
    def test_fetch_and_execute_safe_raises_exception_sleep_is_called(
            self, mock_time_sleep):
        external_task_client = ExternalTaskClient(worker_id=0)
        responses.add(responses.POST,
                      external_task_client.get_fetch_and_lock_url(),
                      status=HTTPStatus.INTERNAL_SERVER_ERROR)

        sleep_seconds = 100
        worker = ExternalTaskWorker(worker_id=0,
                                    config={"sleepSeconds": sleep_seconds})
        mock_action = mock.Mock()

        worker._fetch_and_execute_safe("my_topic", mock_action)

        self.assertEqual(0, mock_action.call_count)
        self.assertEqual(1, mock_time_sleep.call_count)
        mock_time_sleep.assert_called_with(sleep_seconds)
Example #9
0
    def test_fetch_and_execute_raises_exception_if_no_tasks_found(self):
        external_task_client = ExternalTaskClient(worker_id=0)
        resp_payload = []
        responses.add(responses.POST,
                      external_task_client.get_fetch_and_lock_url(),
                      status=HTTPStatus.OK,
                      json=resp_payload)

        worker = ExternalTaskWorker(worker_id=0)
        mock_action = mock.Mock()
        process_variables = {"var1": "value1", "var2": "value2"}
        with self.assertRaises(Exception) as context:
            worker.fetch_and_execute("my_topic", mock_action,
                                     process_variables)

        self.assertEqual(
            f"no External Task found for Topics: my_topic, Process variables: {process_variables}",
            str(context.exception))
Example #10
0
    def test_fetch_and_execute_raises_exception_if_task_action_raises_exception(
            self):
        external_task_client = ExternalTaskClient(worker_id=0)
        resp_payload = [{
            "activityId": "anActivityId",
            "activityInstanceId": "anActivityInstanceId",
            "errorMessage": "anErrorMessage",
            "errorDetails": "anErrorDetails",
            "executionId": "anExecutionId",
            "id": "anExternalTaskId",
            "lockExpirationTime": "2015-10-06T16:34:42",
            "processDefinitionId": "aProcessDefinitionId",
            "processDefinitionKey": "aProcessDefinitionKey",
            "processInstanceId": "aProcessInstanceId",
            "tenantId": None,
            "retries": 3,
            "workerId": "aWorkerId",
            "priority": 4,
            "topicName": "createOrder",
            "variables": {
                "orderId": {
                    "type": "String",
                    "value": "1234",
                    "valueInfo": {}
                }
            }
        }]
        responses.add(responses.POST,
                      external_task_client.get_fetch_and_lock_url(),
                      status=HTTPStatus.OK,
                      json=resp_payload)

        worker = ExternalTaskWorker(worker_id=0)
        mock_action = mock.Mock()
        mock_action.side_effect = Exception("error executing task action")

        with self.assertRaises(Exception) as exception_ctx:
            worker.fetch_and_execute("my_topic", mock_action)

        self.assertEqual("error executing task action",
                         str(exception_ctx.exception))
Example #11
0
 def __init__(self, worker_id, base_url=ENGINE_LOCAL_BASE_URL, config=frozendict({})):
     self.worker_id = worker_id
     self.client = ExternalTaskClient(self.worker_id, base_url, config)
     self.executor = ExternalTaskExecutor(self.worker_id, self.client)
     self.config = config
     self._log_with_context(f"Created new External Task Worker with config: {self.config}")
Example #12
0
    def test_fetch_and_execute_calls_task_action_for_each_task_fetched(
            self, mock_client):
        external_task_client = ExternalTaskClient(worker_id=0)
        resp_payload = [{
            "activityId": "anActivityId",
            "activityInstanceId": "anActivityInstanceId",
            "errorMessage": "anErrorMessage",
            "errorDetails": "anErrorDetails",
            "executionId": "anExecutionId",
            "id": "anExternalTaskId",
            "lockExpirationTime": "2015-10-06T16:34:42",
            "processDefinitionId": "aProcessDefinitionId",
            "processDefinitionKey": "aProcessDefinitionKey",
            "processInstanceId": "aProcessInstanceId",
            "tenantId": None,
            "retries": 3,
            "workerId": "aWorkerId",
            "priority": 4,
            "topicName": "createOrder",
            "variables": {
                "orderId": {
                    "type": "String",
                    "value": "1234",
                    "valueInfo": {}
                }
            }
        }, {
            "activityId": "anActivityId",
            "activityInstanceId": "anActivityInstanceId",
            "errorMessage": "anErrorMessage",
            "errorDetails": "anotherErrorDetails",
            "executionId": "anExecutionId",
            "id": "anExternalTaskId",
            "lockExpirationTime": "2015-10-06T16:34:42",
            "processDefinitionId": "aProcessDefinitionId",
            "processDefinitionKey": "aProcessDefinitionKey",
            "processInstanceId": "aProcessInstanceId",
            "tenantId": None,
            "retries": 3,
            "workerId": "aWorkerId",
            "priority": 0,
            "topicName": "createOrder",
            "variables": {
                "orderId": {
                    "type": "String",
                    "value": "3456",
                    "valueInfo": {}
                }
            }
        }]
        responses.add(responses.POST,
                      external_task_client.get_fetch_and_lock_url(),
                      status=HTTPStatus.OK,
                      json=resp_payload)

        worker = ExternalTaskWorker(worker_id=0)
        mock_action = mock.Mock()
        task = ExternalTask({
            "id": "anExternalTaskId",
            "workerId": "aWorkerId",
            "topicName": "createOrder"
        })
        mock_action.return_value = TaskResult.success(task=task,
                                                      global_variables={})

        worker.fetch_and_execute("my_topic", mock_action)
        self.assertEqual(2, mock_action.call_count)
 def test_creation_with_no_debug_config(self):
     client = ExternalTaskClient(1, ENGINE_LOCAL_BASE_URL, {})
     self.assertFalse(client.is_debug)
     self.assertFalse(client.config.get("isDebug"))