Merge pull request #340 from sartography/bug/better_errors_on_scheduled_tasks
Assure we log reasonably clear errors when executing scheduled tasks …
This commit is contained in:
commit
522ca9d164
|
@ -9,7 +9,7 @@ class GetStudyAssociates(Script):
|
|||
|
||||
def get_description(self):
|
||||
return """
|
||||
Returns person assocated with study or an error if one is not associated.
|
||||
Returns people associated with a study or an error if one is not associated.
|
||||
example : get_study_associate('sbp3ey') => {'uid':'sbp3ey','role':'Unicorn Herder', 'send_email': False,
|
||||
'access':True}
|
||||
|
||||
|
|
|
@ -14,12 +14,12 @@ from crc import db, session, app
|
|||
from crc.api.common import ApiError
|
||||
from crc.models.data_store import DataStoreModel
|
||||
from crc.models.email import EmailModel
|
||||
from crc.models.file import FileDataModel, FileModel, FileModelSchema, File, LookupFileModel, LookupDataModel
|
||||
from crc.models.file import FileModel, File
|
||||
from crc.models.ldap import LdapSchema
|
||||
from crc.models.protocol_builder import ProtocolBuilderStudy, ProtocolBuilderStatus
|
||||
from crc.models.study import StudyModel, Study, StudyStatus, Category, WorkflowMetadata, StudyEventType, StudyEvent, \
|
||||
IrbStatus, StudyAssociated
|
||||
from crc.models.task_event import TaskEventModel, TaskEvent
|
||||
from crc.models.protocol_builder import ProtocolBuilderStudy
|
||||
from crc.models.study import StudyModel, Study, StudyStatus, Category, \
|
||||
WorkflowMetadata, StudyEventType, StudyEvent, IrbStatus, StudyAssociated
|
||||
from crc.models.task_event import TaskEventModel
|
||||
from crc.models.workflow import WorkflowSpecCategoryModel, WorkflowModel, WorkflowSpecModel, WorkflowState, \
|
||||
WorkflowStatus, WorkflowSpecDependencyFile
|
||||
from crc.services.document_service import DocumentService
|
||||
|
|
|
@ -98,15 +98,18 @@ class WorkflowService(object):
|
|||
def do_waiting():
|
||||
records = db.session.query(WorkflowModel).filter(WorkflowModel.status==WorkflowStatus.waiting).all()
|
||||
for workflow_model in records:
|
||||
# fixme: Try catch with a very explicit error about the study, workflow and task that failed.
|
||||
try:
|
||||
app.logger.info('Processing workflow %s' % workflow_model.id)
|
||||
processor = WorkflowProcessor(workflow_model)
|
||||
processor.bpmn_workflow.refresh_waiting_tasks()
|
||||
processor.bpmn_workflow.do_engine_steps()
|
||||
processor.save()
|
||||
except:
|
||||
app.logger.error('Failed to process workflow')
|
||||
except Exception as e:
|
||||
app.logger.error(f"Error running waiting task for workflow #%i (%s) for study #%i. %s" %
|
||||
(workflow_model.id,
|
||||
workflow_model.workflow_spec.name,
|
||||
workflow_model.study_id,
|
||||
str(e)))
|
||||
|
||||
@staticmethod
|
||||
@timeit
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_0ilr8m3" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.3">
|
||||
<bpmn:process id="timer" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_1pahvlr</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:manualTask id="get_coffee" name="Eat Spam">
|
||||
<bpmn:incoming>Flow_1pahvlr</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1pvkgnu</bpmn:outgoing>
|
||||
</bpmn:manualTask>
|
||||
<bpmn:manualTask id="back_to_work" name="Get Back To Work">
|
||||
<bpmn:incoming>Flow_1pvkgnu</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1ekgt3x</bpmn:outgoing>
|
||||
</bpmn:manualTask>
|
||||
<bpmn:endEvent id="Event_03w65sk">
|
||||
<bpmn:incoming>Flow_1ekgt3x</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_1ekgt3x" sourceRef="back_to_work" targetRef="Event_03w65sk" />
|
||||
<bpmn:sequenceFlow id="Flow_1pvkgnu" sourceRef="get_coffee" targetRef="back_to_work" />
|
||||
<bpmn:sequenceFlow id="Flow_1pahvlr" sourceRef="StartEvent_1" targetRef="get_coffee" />
|
||||
<bpmn:sequenceFlow id="Flow_05lcpdf" sourceRef="Event_1txv76c" targetRef="Activity_0onlql2" />
|
||||
<bpmn:scriptTask id="Activity_0onlql2" name="Do Bad Burp">
|
||||
<bpmn:incoming>Flow_05lcpdf</bpmn:incoming>
|
||||
<bpmn:script># Tries to burp, failes.
|
||||
my_burp = non_existent_burp_variable</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:boundaryEvent id="Event_1txv76c" name="burp?" attachedToRef="get_coffee">
|
||||
<bpmn:outgoing>Flow_05lcpdf</bpmn:outgoing>
|
||||
<bpmn:timerEventDefinition id="TimerEventDefinition_1rvot87">
|
||||
<bpmn:timeDuration xsi:type="bpmn:tFormalExpression">timedelta(seconds=.25)</bpmn:timeDuration>
|
||||
</bpmn:timerEventDefinition>
|
||||
</bpmn:boundaryEvent>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="timer">
|
||||
<bpmndi:BPMNEdge id="Flow_1pahvlr_di" bpmnElement="Flow_1pahvlr">
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="260" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1pvkgnu_di" bpmnElement="Flow_1pvkgnu">
|
||||
<di:waypoint x="360" y="117" />
|
||||
<di:waypoint x="533" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1ekgt3x_di" bpmnElement="Flow_1ekgt3x">
|
||||
<di:waypoint x="633" y="117" />
|
||||
<di:waypoint x="682" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_05lcpdf_di" bpmnElement="Flow_05lcpdf">
|
||||
<di:waypoint x="300" y="175" />
|
||||
<di:waypoint x="300" y="180" />
|
||||
<di:waypoint x="380" y="180" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0tjl9dd_di" bpmnElement="get_coffee">
|
||||
<dc:Bounds x="260" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_15zi5m4_di" bpmnElement="back_to_work">
|
||||
<dc:Bounds x="533" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_03w65sk_di" bpmnElement="Event_03w65sk">
|
||||
<dc:Bounds x="682" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_05taua6_di" bpmnElement="Activity_0onlql2">
|
||||
<dc:Bounds x="380" y="140" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_0xco4d9_di" bpmnElement="Event_1txv76c">
|
||||
<dc:Bounds x="282" y="139" width="36" height="36" />
|
||||
<bpmndi:BPMNLabel>
|
||||
<dc:Bounds x="286" y="182" width="29" height="14" />
|
||||
</bpmndi:BPMNLabel>
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
|
@ -1,13 +1,13 @@
|
|||
import json
|
||||
import time
|
||||
|
||||
from crc.services.workflow_processor import WorkflowProcessor
|
||||
from tests.base_test import BaseTest
|
||||
from crc.models.workflow import WorkflowStatus, WorkflowModel
|
||||
from crc import db
|
||||
from crc.api.common import ApiError
|
||||
from crc.models.task_event import TaskEventModel, TaskEventSchema
|
||||
from crc.services.workflow_service import WorkflowService
|
||||
from crc.services.workflow_processor import WorkflowProcessor
|
||||
|
||||
|
||||
class TestTimerEvent(BaseTest):
|
||||
|
@ -28,3 +28,19 @@ class TestTimerEvent(BaseTest):
|
|||
wf = db.session.query(WorkflowModel).filter(WorkflowModel.id == workflow.id).first()
|
||||
self.assertTrue(wf.status != WorkflowStatus.waiting)
|
||||
|
||||
def test_waiting_event_error(self):
|
||||
workflow = self.create_workflow('timer_event_error')
|
||||
processor = WorkflowProcessor(workflow)
|
||||
processor.do_engine_steps()
|
||||
processor.save()
|
||||
time.sleep(.3) # our timer is at .25 sec so we have to wait for it
|
||||
# get done waiting
|
||||
wf = db.session.query(WorkflowModel).filter(WorkflowModel.id == workflow.id).first()
|
||||
self.assertTrue(wf.status == WorkflowStatus.waiting)
|
||||
with self.assertLogs('crc', level='ERROR') as cm:
|
||||
WorkflowService.do_waiting()
|
||||
self.assertEqual(1, len(cm.output))
|
||||
self.assertRegexpMatches(cm.output[0], f"workflow #%i" % workflow.id)
|
||||
self.assertRegexpMatches(cm.output[0], f"study #%i" % workflow.study_id)
|
||||
|
||||
self.assertTrue(wf.status == WorkflowStatus.waiting)
|
||||
|
|
Loading…
Reference in New Issue