Restart workflow without form data. Committing so Dan can check it out
This commit is contained in:
parent
99c1d1b129
commit
6a9e6d3570
|
@ -852,16 +852,16 @@ paths:
|
||||||
operationId: crc.api.workflow.get_workflow
|
operationId: crc.api.workflow.get_workflow
|
||||||
summary: Returns a workflow, can also be used to do a soft or hard reset on the workflow.
|
summary: Returns a workflow, can also be used to do a soft or hard reset on the workflow.
|
||||||
parameters:
|
parameters:
|
||||||
- name: soft_reset
|
- name: clear_data
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
description: Set this to true to use the latest workflow specification to load minor modifications to the spec.
|
description: Set this to true to clear data when starting workflow.
|
||||||
schema:
|
schema:
|
||||||
type: boolean
|
type: boolean
|
||||||
- name: hard_reset
|
- name: reload_spec
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
description: Set this to true to reset the workflow
|
description: Set this to true to load latest workflow spec.
|
||||||
schema:
|
schema:
|
||||||
type: boolean
|
type: boolean
|
||||||
- name: do_engine_steps
|
- name: do_engine_steps
|
||||||
|
|
|
@ -96,27 +96,35 @@ def delete_workflow_specification(spec_id):
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
def get_workflow(workflow_id, soft_reset=False, hard_reset=False, do_engine_steps=True):
|
def get_workflow(workflow_id, reload_spec=False, clear_data=False, do_engine_steps=True):
|
||||||
"""Soft reset will attempt to update to the latest spec without starting over,
|
"""Soft reset will attempt to update to the latest spec without starting over,
|
||||||
Hard reset will update to the latest spec and start from the beginning.
|
Hard reset will update to the latest spec and start from the beginning.
|
||||||
Read Only will return the workflow in a read only state, without running any
|
Read Only will return the workflow in a read only state, without running any
|
||||||
engine tasks or logging any events. """
|
engine tasks or logging any events. """
|
||||||
workflow_model: WorkflowModel = session.query(WorkflowModel).filter_by(id=workflow_id).first()
|
workflow_model: WorkflowModel = session.query(WorkflowModel).filter_by(id=workflow_id).first()
|
||||||
processor = WorkflowProcessor(workflow_model)
|
processor = WorkflowProcessor(workflow_model, reload_spec=reload_spec, clear_data=clear_data)
|
||||||
if soft_reset or hard_reset:
|
if reload_spec or clear_data:
|
||||||
try:
|
try:
|
||||||
processor.cancel_notify()
|
processor.cancel_notify()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise e
|
raise e
|
||||||
finally:
|
finally:
|
||||||
# In the event of a reset, ALWAYS allow the reset, even if the cancel_notify fails for some reason.
|
# In the event of a reset, ALWAYS allow the reset, even if the cancel_notify fails for some reason.
|
||||||
processor = WorkflowProcessor(workflow_model, soft_reset=soft_reset, hard_reset=hard_reset)
|
processor = WorkflowProcessor(workflow_model, reload_spec=reload_spec, clear_data=clear_data)
|
||||||
|
|
||||||
if do_engine_steps:
|
if do_engine_steps:
|
||||||
processor.do_engine_steps()
|
processor.do_engine_steps()
|
||||||
processor.save()
|
processor.save()
|
||||||
WorkflowService.update_task_assignments(processor)
|
WorkflowService.update_task_assignments(processor)
|
||||||
workflow_api_model = WorkflowService.processor_to_workflow_api(processor)
|
workflow_api_model = WorkflowService.processor_to_workflow_api(processor)
|
||||||
|
if clear_data:
|
||||||
|
remove_keys = []
|
||||||
|
for datum in workflow_api_model.next_task.data:
|
||||||
|
if datum != 'current_user':
|
||||||
|
remove_keys.append(datum)
|
||||||
|
if len(remove_keys) > 0:
|
||||||
|
for key in remove_keys:
|
||||||
|
del(workflow_api_model.next_task.data[key])
|
||||||
return WorkflowApiSchema().dump(workflow_api_model)
|
return WorkflowApiSchema().dump(workflow_api_model)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import crc
|
||||||
from crc import session, app
|
from crc import session, app
|
||||||
from crc.api.common import ApiError
|
from crc.api.common import ApiError
|
||||||
from crc.models.file import FileDataModel, FileModel, FileType
|
from crc.models.file import FileDataModel, FileModel, FileType
|
||||||
|
from crc.models.task_event import TaskEventModel
|
||||||
from crc.models.workflow import WorkflowStatus, WorkflowModel, WorkflowSpecDependencyFile
|
from crc.models.workflow import WorkflowStatus, WorkflowModel, WorkflowSpecDependencyFile
|
||||||
from crc.scripts.script import Script
|
from crc.scripts.script import Script
|
||||||
from crc.services.file_service import FileService
|
from crc.services.file_service import FileService
|
||||||
|
@ -151,7 +152,7 @@ class WorkflowProcessor(object):
|
||||||
VALIDATION_PROCESS_KEY = "validate_only"
|
VALIDATION_PROCESS_KEY = "validate_only"
|
||||||
|
|
||||||
def __init__(self, workflow_model: WorkflowModel,
|
def __init__(self, workflow_model: WorkflowModel,
|
||||||
soft_reset=False, hard_reset=False, validate_only=False):
|
reload_spec=False, clear_data=False, validate_only=False):
|
||||||
"""Create a Workflow Processor based on the serialized information available in the workflow model.
|
"""Create a Workflow Processor based on the serialized information available in the workflow model.
|
||||||
If soft_reset is set to true, it will try to use the latest version of the workflow specification
|
If soft_reset is set to true, it will try to use the latest version of the workflow specification
|
||||||
without resetting to the beginning of the workflow. This will work for some minor changes to the spec.
|
without resetting to the beginning of the workflow. This will work for some minor changes to the spec.
|
||||||
|
@ -162,7 +163,7 @@ class WorkflowProcessor(object):
|
||||||
|
|
||||||
self.workflow_model = workflow_model
|
self.workflow_model = workflow_model
|
||||||
|
|
||||||
if soft_reset or len(workflow_model.dependencies) == 0: # Depenencies of 0 means the workflow was never started.
|
if reload_spec or len(workflow_model.dependencies) == 0: # Depenencies of 0 means the workflow was never started.
|
||||||
self.spec_data_files = FileService.get_spec_data_files(
|
self.spec_data_files = FileService.get_spec_data_files(
|
||||||
workflow_spec_id=workflow_model.workflow_spec_id)
|
workflow_spec_id=workflow_model.workflow_spec_id)
|
||||||
spec = self.get_spec(self.spec_data_files, workflow_model.workflow_spec_id)
|
spec = self.get_spec(self.spec_data_files, workflow_model.workflow_spec_id)
|
||||||
|
@ -196,13 +197,17 @@ class WorkflowProcessor(object):
|
||||||
" '%s' version %s, due to a mis-placed or missing task '%s'" %
|
" '%s' version %s, due to a mis-placed or missing task '%s'" %
|
||||||
(self.workflow_spec_id, self.get_version_string(), str(ke)) +
|
(self.workflow_spec_id, self.get_version_string(), str(ke)) +
|
||||||
" This is very likely due to a soft reset where there was a structural change.")
|
" This is very likely due to a soft reset where there was a structural change.")
|
||||||
if hard_reset:
|
if clear_data:
|
||||||
# Now that the spec is loaded, get the data and rebuild the bpmn with the new details
|
# Clear form_data from task_events
|
||||||
self.hard_reset()
|
task_events = session.query(TaskEventModel). \
|
||||||
|
filter(TaskEventModel.workflow_id == workflow_model.id).all()
|
||||||
|
for task_event in task_events:
|
||||||
|
task_event.form_data = {}
|
||||||
|
session.add(task_event)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
workflow_model.bpmn_workflow_json = WorkflowProcessor._serializer.serialize_workflow(self.bpmn_workflow)
|
workflow_model.bpmn_workflow_json = WorkflowProcessor._serializer.serialize_workflow(self.bpmn_workflow)
|
||||||
self.save()
|
self.save()
|
||||||
if soft_reset:
|
|
||||||
self.save()
|
|
||||||
|
|
||||||
# set whether this is the latest spec file.
|
# set whether this is the latest spec file.
|
||||||
if self.spec_data_files == FileService.get_spec_data_files(workflow_spec_id=workflow_model.workflow_spec_id):
|
if self.spec_data_files == FileService.get_spec_data_files(workflow_spec_id=workflow_model.workflow_spec_id):
|
||||||
|
@ -355,18 +360,18 @@ class WorkflowProcessor(object):
|
||||||
else:
|
else:
|
||||||
return WorkflowStatus.waiting
|
return WorkflowStatus.waiting
|
||||||
|
|
||||||
def hard_reset(self):
|
# def hard_reset(self):
|
||||||
"""Recreate this workflow. This will be useful when a workflow specification changes.
|
# """Recreate this workflow. This will be useful when a workflow specification changes.
|
||||||
"""
|
# """
|
||||||
self.spec_data_files = FileService.get_spec_data_files(workflow_spec_id=self.workflow_spec_id)
|
# self.spec_data_files = FileService.get_spec_data_files(workflow_spec_id=self.workflow_spec_id)
|
||||||
new_spec = WorkflowProcessor.get_spec(self.spec_data_files, self.workflow_spec_id)
|
# new_spec = WorkflowProcessor.get_spec(self.spec_data_files, self.workflow_spec_id)
|
||||||
new_bpmn_workflow = BpmnWorkflow(new_spec, script_engine=self._script_engine)
|
# new_bpmn_workflow = BpmnWorkflow(new_spec, script_engine=self._script_engine)
|
||||||
new_bpmn_workflow.data = self.bpmn_workflow.data
|
# new_bpmn_workflow.data = self.bpmn_workflow.data
|
||||||
try:
|
# try:
|
||||||
new_bpmn_workflow.do_engine_steps()
|
# new_bpmn_workflow.do_engine_steps()
|
||||||
except WorkflowException as we:
|
# except WorkflowException as we:
|
||||||
raise ApiError.from_task_spec("hard_reset_engine_steps_error", str(we), we.sender)
|
# raise ApiError.from_task_spec("hard_reset_engine_steps_error", str(we), we.sender)
|
||||||
self.bpmn_workflow = new_bpmn_workflow
|
# self.bpmn_workflow = new_bpmn_workflow
|
||||||
|
|
||||||
def get_status(self):
|
def get_status(self):
|
||||||
return self.status_of(self.bpmn_workflow)
|
return self.status_of(self.bpmn_workflow)
|
||||||
|
|
|
@ -341,13 +341,14 @@ class BaseTest(unittest.TestCase):
|
||||||
session.commit()
|
session.commit()
|
||||||
return approval
|
return approval
|
||||||
|
|
||||||
def get_workflow_api(self, workflow, soft_reset=False, hard_reset=False, do_engine_steps=True, user_uid="dhf8r"):
|
def get_workflow_api(self, workflow, reload_spec=False, clear_data=False, do_engine_steps=True, user_uid="dhf8r"):
|
||||||
user = session.query(UserModel).filter_by(uid=user_uid).first()
|
user = session.query(UserModel).filter_by(uid=user_uid).first()
|
||||||
self.assertIsNotNone(user)
|
self.assertIsNotNone(user)
|
||||||
rv = self.app.get(f'/v1.0/workflow/{workflow.id}'
|
url = (f'/v1.0/workflow/{workflow.id}'
|
||||||
f'?soft_reset={str(soft_reset)}'
|
f'?clear_data={str(clear_data)}'
|
||||||
f'&hard_reset={str(hard_reset)}'
|
f'&reload_spec={str(reload_spec)}'
|
||||||
f'&do_engine_steps={str(do_engine_steps)}',
|
f'&do_engine_steps={str(do_engine_steps)}')
|
||||||
|
rv = self.app.get(url,
|
||||||
headers=self.logged_in_headers(user),
|
headers=self.logged_in_headers(user),
|
||||||
content_type="application/json")
|
content_type="application/json")
|
||||||
self.assert_success(rv)
|
self.assert_success(rv)
|
||||||
|
|
|
@ -5,14 +5,16 @@ class TestMessageEvent(BaseTest):
|
||||||
|
|
||||||
def test_message_event(self):
|
def test_message_event(self):
|
||||||
|
|
||||||
|
# self.load_example_data()
|
||||||
workflow = self.create_workflow('message_event')
|
workflow = self.create_workflow('message_event')
|
||||||
|
|
||||||
first_task = self.get_workflow_api(workflow).next_task
|
first_task = self.get_workflow_api(workflow).next_task
|
||||||
self.assertEqual('Activity_GetData', first_task.name)
|
self.assertEqual('Activity_GetData', first_task.name)
|
||||||
workflow_api = self.get_workflow_api(workflow, clear_data=True)
|
workflow_api = self.get_workflow_api(workflow)
|
||||||
result = self.complete_form(workflow_api, first_task, {'name': 'asdf'})
|
result = self.complete_form(workflow_api, first_task, {'formdata': 'asdf'})
|
||||||
self.assertEqual('asdf', result.next_task.data['name'])
|
self.assertIn('formdata', result.next_task.data)
|
||||||
workflow_api = self.get_workflow_api(workflow_api)
|
self.assertEqual('asdf', result.next_task.data['formdata'])
|
||||||
self.assertNotIn('name', workflow_api.next_task.data)
|
workflow_api = self.get_workflow_api(workflow_api, clear_data=True)
|
||||||
|
self.assertNotIn('formdata', workflow_api.next_task.data)
|
||||||
|
|
||||||
print('Nice Test')
|
print('Nice Test')
|
||||||
|
|
Loading…
Reference in New Issue