Assure we log reasonably clear errors when executing scheduled tasks in the background, so that sentry can pick them up and they can be addressed effectively.
This commit is contained in:
parent
bef35e4bec
commit
1916c4ff54
|
@ -98,15 +98,18 @@ class WorkflowService(object):
|
||||||
def do_waiting():
|
def do_waiting():
|
||||||
records = db.session.query(WorkflowModel).filter(WorkflowModel.status==WorkflowStatus.waiting).all()
|
records = db.session.query(WorkflowModel).filter(WorkflowModel.status==WorkflowStatus.waiting).all()
|
||||||
for workflow_model in records:
|
for workflow_model in records:
|
||||||
# fixme: Try catch with a very explicit error about the study, workflow and task that failed.
|
|
||||||
try:
|
try:
|
||||||
app.logger.info('Processing workflow %s' % workflow_model.id)
|
app.logger.info('Processing workflow %s' % workflow_model.id)
|
||||||
processor = WorkflowProcessor(workflow_model)
|
processor = WorkflowProcessor(workflow_model)
|
||||||
processor.bpmn_workflow.refresh_waiting_tasks()
|
processor.bpmn_workflow.refresh_waiting_tasks()
|
||||||
processor.bpmn_workflow.do_engine_steps()
|
processor.bpmn_workflow.do_engine_steps()
|
||||||
processor.save()
|
processor.save()
|
||||||
except:
|
except Exception as e:
|
||||||
app.logger.error('Failed to process workflow')
|
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
|
@staticmethod
|
||||||
@timeit
|
@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 json
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from crc.services.workflow_processor import WorkflowProcessor
|
|
||||||
from tests.base_test import BaseTest
|
from tests.base_test import BaseTest
|
||||||
from crc.models.workflow import WorkflowStatus, WorkflowModel
|
from crc.models.workflow import WorkflowStatus, WorkflowModel
|
||||||
from crc import db
|
from crc import db
|
||||||
from crc.api.common import ApiError
|
from crc.api.common import ApiError
|
||||||
from crc.models.task_event import TaskEventModel, TaskEventSchema
|
from crc.models.task_event import TaskEventModel, TaskEventSchema
|
||||||
from crc.services.workflow_service import WorkflowService
|
from crc.services.workflow_service import WorkflowService
|
||||||
|
from crc.services.workflow_processor import WorkflowProcessor
|
||||||
|
|
||||||
|
|
||||||
class TestTimerEvent(BaseTest):
|
class TestTimerEvent(BaseTest):
|
||||||
|
@ -28,3 +28,19 @@ class TestTimerEvent(BaseTest):
|
||||||
wf = db.session.query(WorkflowModel).filter(WorkflowModel.id == workflow.id).first()
|
wf = db.session.query(WorkflowModel).filter(WorkflowModel.id == workflow.id).first()
|
||||||
self.assertTrue(wf.status != WorkflowStatus.waiting)
|
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], "workflow #1")
|
||||||
|
self.assertRegexpMatches(cm.output[0], "study #1")
|
||||||
|
|
||||||
|
self.assertTrue(wf.status == WorkflowStatus.waiting)
|
||||||
|
|
Loading…
Reference in New Issue