From 234c9646e1fe3ee517a7a39b4263f84f576a58ff Mon Sep 17 00:00:00 2001 From: jasquat <2487833+jasquat@users.noreply.github.com> Date: Fri, 27 Oct 2023 15:01:28 -0400 Subject: [PATCH] feature/skip-user-input-required-tasks (#596) * only check for timer events in ready_user_task_has_associated_timer so we can skip user_input_required instances w/ burnettk * removed test.py file w/ burnettk --------- Co-authored-by: jasquat --- .../bin/run_local_python_script | 15 +++++++++++++++ .../services/process_instance_service.py | 19 ++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100755 spiffworkflow-backend/bin/run_local_python_script diff --git a/spiffworkflow-backend/bin/run_local_python_script b/spiffworkflow-backend/bin/run_local_python_script new file mode 100755 index 00000000..f2b97d4d --- /dev/null +++ b/spiffworkflow-backend/bin/run_local_python_script @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +function error_handler() { + >&2 echo "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}." + exit "$2" +} +trap 'error_handler ${LINENO} $?' ERR +set -o errtrace -o errexit -o nounset -o pipefail + +script_dir="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +. "${script_dir}/local_development_environment_setup" + +export SPIFFWORKFLOW_BACKEND_RUN_BACKGROUND_SCHEDULER_IN_CREATE_APP=false + +poet run python "$@" 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 451c4116..c79eb9af 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_service.py @@ -12,6 +12,7 @@ from flask import current_app from flask import g from SpiffWorkflow.bpmn.event import PendingBpmnEvent # type: ignore from SpiffWorkflow.bpmn.specs.control import BoundaryEventSplit # type: ignore +from SpiffWorkflow.bpmn.specs.defaults import BoundaryEvent # type: ignore from SpiffWorkflow.bpmn.specs.event_definitions.timer import TimerEventDefinition # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.util.task import TaskState # type: ignore @@ -204,7 +205,13 @@ class ProcessInstanceService: def ready_user_task_has_associated_timer(cls, processor: ProcessInstanceProcessor) -> bool: for ready_user_task in processor.bpmn_process_instance.get_tasks(state=TaskState.READY, manual=True): if isinstance(ready_user_task.parent.task_spec, BoundaryEventSplit): - return True + for boundary_event_child in ready_user_task.parent.children: + child_task_spec = boundary_event_child.task_spec + if ( + isinstance(child_task_spec, BoundaryEvent) + and "Timer" in child_task_spec.event_definition.__class__.__name__ + ): + return True return False @classmethod @@ -215,8 +222,10 @@ class ProcessInstanceService: if processor.process_instance_model.status != status_value: return True - if status_value == "user_input_required" and cls.ready_user_task_has_associated_timer(processor): - return cls.all_waiting_events_can_be_skipped(processor.bpmn_process_instance.waiting_events()) + if status_value == "user_input_required": + if cls.ready_user_task_has_associated_timer(processor): + return cls.all_waiting_events_can_be_skipped(processor.bpmn_process_instance.waiting_events()) + return True return False @@ -265,6 +274,10 @@ class ProcessInstanceService: processor = ProcessInstanceProcessor( process_instance, workflow_completed_handler=cls.schedule_next_process_model_cycle ) + + # if status_value is user_input_required (we are processing instances with that status from background processor), + # the ONLY reason we need to do anything is if the task has a timer boundary event on it that has triggered. + # otherwise, in all cases, we should optimistically skip it. if status_value and cls.can_optimistically_skip(processor, status_value): current_app.logger.info(f"Optimistically skipped process_instance {process_instance.id}") return None