GitLab will be upgraded on June 23rd evening. During the upgrade the service will be unavailable, sorry for the inconvenience.

Commit fe3637d2 authored by Olof Svensson's avatar Olof Svensson

BES-301 : Improved error handling when importing scripts, renamed...

BES-301 : Improved error handling when importing scripts, renamed "WorkflowException" to "ActorWrapperException" in order to avoid confusion with "workflowException" in outData
parent bef379ae
......@@ -24,6 +24,7 @@ __license__ = "MIT"
__date__ = "28/05/2019"
import os
import time
import pprint
import logging
import datetime
......@@ -39,10 +40,10 @@ from pypushflow.AbstractActor import AbstractActor
logger = logging.getLogger('pypushflow')
class WorkflowException(Exception):
class ActorWrapperException(Exception):
def __init__(self, errorMessage="", traceBack="", data={}, msg=None):
super(WorkflowException, self).__init__(msg)
super(ActorWrapperException, self).__init__(msg)
self.errorMessage = errorMessage
self.data = data
self.traceBack = traceBack
......@@ -57,7 +58,7 @@ def trace_unhandled_exceptions(func):
errorMessage = '{0}'.format(e)
logger.exception(errorMessage)
traceBack = traceback.format_exc()
return WorkflowException(
return ActorWrapperException(
errorMessage=errorMessage,
traceBack=traceBack,
data=args[1]
......@@ -135,12 +136,13 @@ class PythonActor(AbstractActor):
def __init__(self, parent=None, name='Python Actor', errorHandler=None, script=None):
AbstractActor.__init__(self, parent=parent, name=name)
self.errorHandler = errorHandler
self.parentErrorHandler = errorHandler
self.listErrorHandler = []
# Import script
self.script = script
module = importlib.import_module(os.path.splitext(script)[0])
self.actorWrapper = ActorWrapper(name, module.run)
# module = importlib.import_module(os.path.splitext(script)[0])
# self.actorWrapper = ActorWrapper(name, module.run)
self.actorWrapper = None
self.inData = None
self.outData = None
self.af = None
......@@ -153,9 +155,9 @@ class PythonActor(AbstractActor):
self.inData = dict(inData)
self.uploadInDataToMongo(actorData={'inData': inData}, script=self.script)
logger.debug('In trigger {0}, inData = {1}'.format(self.name, pprint.pformat(inData)))
if isinstance(inData, WorkflowException):
if isinstance(inData, ActorWrapperException):
logger.error('Error from previous actor! Not running actor {0}'.format(self.name))
if self.errorHandler is not None:
if self.parentErrorHandler is not None:
workflowException = inData
oldInData = workflowException.data
exceptionDict = {
......@@ -163,31 +165,45 @@ class PythonActor(AbstractActor):
'traceBack': workflowException.traceBack.split('\n'),
}
oldInData['WorkflowException'] = exceptionDict
self.triggerOnError(oldInData)
self.af = AsyncFactory(self.actorWrapper.run,
callback=self.triggerDownStreamActor,
errorCallback=self.errorHandler)
self.af.call(self.inData)
self.parentErrorHandler.triggerOnError(oldInData)
try:
module = importlib.import_module(os.path.splitext(self.script)[0])
except Exception as e:
logger.error('Error when trying to import script {0}'.format(self.script))
time.sleep(1)
self.errorHandler(inData, e)
else:
actorWrapper = ActorWrapper(self.name, module.run)
self.af = AsyncFactory(actorWrapper.run,
callback=self.triggerDownStreamActor,
errorCallback=self.errorHandler)
self.af.call(self.inData)
def errorHandler(self, exception):
def errorHandler(self, inData, exception):
logger.error('Error when running actor {0}!'.format(self.name))
self.setFinished()
workflowException = WorkflowException(
errorMessage=exception,
traceBack=None,
data=None
)
inData = {'WorkflowException': workflowException}
errorMessage = '{0}'.format(exception)
logger.exception(errorMessage)
traceBack = traceback.format_exc().split("\n")
# workflowException = WorkflowException(
# errorMessage=errorMessage,
# traceBack=traceBack
# )
outData = dict(inData)
outData['WorkflowException'] = {
"errorMessage": errorMessage,
"traceBack": traceBack
}
logger.error(exception)
for errorHandler in self.listErrorHandler:
errorHandler.trigger(inData)
if self.errorHandler is not None:
self.errorHandler.triggerOnError(inData)
errorHandler.trigger(outData)
if self.parentErrorHandler is not None:
self.parentErrorHandler.triggerOnError(outData)
def triggerDownStreamActor(self, inData={}):
logger.debug('In triggerDownStreamActor for {0}'.format(self.name))
self.setFinished()
if isinstance(inData, WorkflowException):
if isinstance(inData, ActorWrapperException):
logger.error('Error from previous actor! Not running down stream actors {0}'.format([actor.name for actor in self.listDownStreamActor]))
workflowException = inData
oldInData = workflowException.data
......@@ -203,9 +219,9 @@ class PythonActor(AbstractActor):
})
for errorHandler in self.listErrorHandler:
errorHandler.trigger(oldInData)
if self.errorHandler is not None:
logger.error('Trigger on error on errorHandler "{0}"'.format(self.errorHandler.name))
self.errorHandler.triggerOnError(inData=oldInData)
if self.parentErrorHandler is not None:
logger.error('Trigger on error on errorHandler "{0}"'.format(self.parentErrorHandler.name))
self.parentErrorHandler.triggerOnError(inData=oldInData)
else:
outData = dict(inData)
self.uploadOutDataToMongo(actorData={
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment