Feature/reset pi go button (#978)
* delete human task for task that is being reset to in a process instance w/ burnettk * added script to remove duplicate human tasks from the database w/ burnettk * test that human tasks are not duplicated during pi reset w/ burnettk --------- Co-authored-by: jasquat <jasquat@users.noreply.github.com>
This commit is contained in:
parent
a61f2d6927
commit
5ae59367cb
|
@ -5,6 +5,7 @@ from spiffworkflow_backend import create_app
|
|||
from spiffworkflow_backend.data_migrations.version_1_3 import VersionOneThree
|
||||
from spiffworkflow_backend.data_migrations.version_2 import Version2
|
||||
from spiffworkflow_backend.models.db import db
|
||||
from spiffworkflow_backend.models.human_task import HumanTaskModel
|
||||
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
|
||||
from sqlalchemy import update
|
||||
|
||||
|
@ -39,6 +40,27 @@ def put_serializer_version_onto_numeric_track() -> None:
|
|||
db.session.commit()
|
||||
|
||||
|
||||
@benchmark_log_func
|
||||
def remove_duplicate_human_task_rows() -> None:
|
||||
result = (
|
||||
db.session.query(HumanTaskModel.process_instance_id, HumanTaskModel.task_guid, db.func.count().label("ct"))
|
||||
.group_by(HumanTaskModel.task_guid, HumanTaskModel.process_instance_id)
|
||||
.having(db.func.count() > 1)
|
||||
.all()
|
||||
)
|
||||
|
||||
# Process the result as needed
|
||||
rows_to_delete = []
|
||||
for row in result:
|
||||
human_tasks = (
|
||||
HumanTaskModel.query.filter_by(task_guid=row.task_guid).order_by(HumanTaskModel.created_at_in_seconds.desc()).all()
|
||||
)
|
||||
rows_to_delete = rows_to_delete + human_tasks[1:]
|
||||
for row in rows_to_delete:
|
||||
db.session.delete(row)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def all_potentially_relevant_process_instances() -> list[ProcessInstanceModel]:
|
||||
return ProcessInstanceModel.query.filter(
|
||||
ProcessInstanceModel.spiff_serializer_version < Version2.version(),
|
||||
|
@ -65,6 +87,7 @@ def main() -> None:
|
|||
current_app.logger.debug(f"data_migrations/run_all::create_app took {end_time - start_time} seconds")
|
||||
start_time = time.time()
|
||||
put_serializer_version_onto_numeric_track()
|
||||
remove_duplicate_human_task_rows()
|
||||
process_instances = all_potentially_relevant_process_instances()
|
||||
potentially_relevant_instance_count = len(process_instances)
|
||||
current_app.logger.debug(f"Found potentially relevant process_instances: {potentially_relevant_instance_count}")
|
||||
|
|
|
@ -1230,7 +1230,7 @@ class ProcessInstanceProcessor:
|
|||
serializer=processor._serializer,
|
||||
bpmn_definition_to_task_definitions_mappings=processor.bpmn_definition_to_task_definitions_mappings,
|
||||
)
|
||||
task_service.update_all_tasks_from_spiff_tasks(spiff_tasks, deleted_tasks, start_time)
|
||||
task_service.update_all_tasks_from_spiff_tasks(spiff_tasks, deleted_tasks, start_time, to_task_guid=to_task_guid)
|
||||
|
||||
# Save the process
|
||||
processor.save()
|
||||
|
|
|
@ -446,13 +446,25 @@ class TaskService:
|
|||
self.task_models[task_model.guid] = task_model
|
||||
|
||||
def update_all_tasks_from_spiff_tasks(
|
||||
self, spiff_tasks: list[SpiffTask], deleted_spiff_tasks: list[SpiffTask], start_time: float
|
||||
self,
|
||||
spiff_tasks: list[SpiffTask],
|
||||
deleted_spiff_tasks: list[SpiffTask],
|
||||
start_time: float,
|
||||
to_task_guid: str | None = None,
|
||||
) -> None:
|
||||
"""Update given spiff tasks in the database and remove deleted tasks."""
|
||||
# Remove all the deleted/pruned tasks from the database.
|
||||
deleted_task_guids = [str(t.id) for t in deleted_spiff_tasks]
|
||||
tasks_to_clear = TaskModel.query.filter(TaskModel.guid.in_(deleted_task_guids)).all() # type: ignore
|
||||
human_tasks_to_clear = HumanTaskModel.query.filter(HumanTaskModel.task_id.in_(deleted_task_guids)).all() # type: ignore
|
||||
|
||||
human_task_guids_to_clear = deleted_task_guids
|
||||
|
||||
# ensure we clear out any human tasks that were associated with this guid in case it was a human task
|
||||
if to_task_guid is not None:
|
||||
human_task_guids_to_clear.append(to_task_guid)
|
||||
human_tasks_to_clear = HumanTaskModel.query.filter(
|
||||
HumanTaskModel.task_id.in_(human_task_guids_to_clear) # type: ignore
|
||||
).all()
|
||||
|
||||
# delete human tasks first to avoid potential conflicts when deleting tasks.
|
||||
# otherwise sqlalchemy returns several warnings.
|
||||
|
|
|
@ -257,14 +257,18 @@ class TestProcessInstanceProcessor(BaseTest):
|
|||
human_task_one.task_name, processor.bpmn_process_instance
|
||||
)
|
||||
assert spiff_manual_task is not None
|
||||
ProcessInstanceService.complete_form_task(processor, spiff_manual_task, {}, initiator_user, human_task_one)
|
||||
|
||||
processor.suspend()
|
||||
ProcessInstanceProcessor.reset_process(process_instance, str(spiff_manual_task.parent.id))
|
||||
ProcessInstanceProcessor.reset_process(process_instance, str(spiff_manual_task.id))
|
||||
|
||||
process_instance = ProcessInstanceModel.query.filter_by(id=process_instance.id).first()
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
processor.resume()
|
||||
processor.do_engine_steps(save=True)
|
||||
|
||||
# if if there are more human tasks then they were duplicated in the reset process method
|
||||
assert len(process_instance.human_tasks) == 1
|
||||
human_task_one = process_instance.active_human_tasks[0]
|
||||
spiff_manual_task = processor.bpmn_process_instance.get_task_from_id(UUID(human_task_one.task_id))
|
||||
ProcessInstanceService.complete_form_task(processor, spiff_manual_task, {}, initiator_user, human_task_one)
|
||||
|
|
Loading…
Reference in New Issue