From 4059f63fb6100255141b2581fa73b1ac31e1cf3e Mon Sep 17 00:00:00 2001 From: jasquat <2487833+jasquat@users.noreply.github.com> Date: Wed, 12 Jul 2023 10:16:05 -0400 Subject: [PATCH] catch and handle exceptions when attempting to complete human tasks (#380) * catch and handle exceptions when attempting to complete human tasks w/ burnettk * fix lint --------- Co-authored-by: jasquat Co-authored-by: burnettk --- .../routes/process_instance_events_controller.py | 15 ++++++++++++++- .../routes/tasks_controller.py | 2 +- .../services/process_instance_processor.py | 15 +++++++++++++-- .../services/process_instance_service.py | 3 +++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instance_events_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instance_events_controller.py index 4e2a0ac64..c72c72f29 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instance_events_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instance_events_controller.py @@ -138,4 +138,17 @@ def error_detail_show( status_code=400, ) ) - return make_response(jsonify(process_instance_event.error_details[0]), 200) + if len(process_instance_event.error_details) < 1: + raise ( + ApiError( + error_code="process_instance_event_error_details_not_found", + message=( + f"Error details for process instance event could not be found: {process_instance_event_id}. " + "Perhaps no exception was available." + ), + status_code=400, + ) + ) + + error_details = process_instance_event.error_details[0] + return make_response(jsonify(error_details), 200) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py index 5aa52ce77..d50857703 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py @@ -602,7 +602,7 @@ def task_save_draft( error_code="process_instance_not_runnable", message=( f"Process Instance ({process_instance.id}) has status " - f"{process_instance.status} which does not allow tasks to be submitted." + f"{process_instance.status} which does not allow draft data to be saved." ), status_code=400, ) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py index 896ac2b06..f3989f5bd 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -1541,7 +1541,14 @@ class ProcessInstanceProcessor: ) task_model.start_in_seconds = time.time() - self.bpmn_process_instance.run_task_from_id(spiff_task.id) + task_exception = None + task_event = ProcessInstanceEventType.task_completed.value + try: + self.bpmn_process_instance.run_task_from_id(spiff_task.id) + except Exception as ex: + task_exception = ex + task_event = ProcessInstanceEventType.task_failed.value + task_model.end_in_seconds = time.time() human_task.completed_by_user_id = user.id @@ -1559,9 +1566,10 @@ class ProcessInstanceProcessor: ProcessInstanceTmpService.add_event_to_process_instance( self.process_instance_model, - ProcessInstanceEventType.task_completed.value, + task_event, task_guid=task_model.guid, user_id=user.id, + exception=task_exception, ) # children of a multi-instance task has the attribute "triggered" set to True @@ -1577,6 +1585,9 @@ class ProcessInstanceProcessor: # this is the thing that actually commits the db transaction (on behalf of the other updates above as well) self.save() + if task_exception is not None: + raise task_exception + def get_data(self) -> dict[str, Any]: return self.bpmn_process_instance.data # type: ignore diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py index 0f144e473..264c73ffb 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py @@ -25,6 +25,7 @@ from spiffworkflow_backend.models.process_model_cycle import ProcessModelCycleMo from spiffworkflow_backend.models.task import Task from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.services.authorization_service import AuthorizationService +from spiffworkflow_backend.services.authorization_service import HumanTaskAlreadyCompletedError from spiffworkflow_backend.services.authorization_service import HumanTaskNotFoundError from spiffworkflow_backend.services.authorization_service import UserDoesNotHaveAccessToTaskError from spiffworkflow_backend.services.git_service import GitCommandError @@ -524,6 +525,8 @@ class ProcessInstanceService: processor.process_instance_model.id, str(spiff_task.id), g.user ) can_complete = True + except HumanTaskAlreadyCompletedError: + can_complete = False except HumanTaskNotFoundError: can_complete = False except UserDoesNotHaveAccessToTaskError: