Merge "Make sure not to swallow original exceptions on handling remote errors"
This commit is contained in:
commit
c77e230a48
@ -65,18 +65,20 @@ def validate_long_type_length(cls, field_name, value):
|
|||||||
size_kb = int(sys.getsizeof(str(value)) / 1024)
|
size_kb = int(sys.getsizeof(str(value)) / 1024)
|
||||||
|
|
||||||
if size_kb > size_limit_kb:
|
if size_kb > size_limit_kb:
|
||||||
LOG.error(
|
msg = (
|
||||||
"Size limit %dKB exceed for class [%s], "
|
"Field size limit exceeded"
|
||||||
"field %s of size %dKB.",
|
" [class={}, field={}, size={}KB, limit={}KB]"
|
||||||
size_limit_kb, str(cls), field_name, size_kb
|
).format(
|
||||||
)
|
cls.__name__,
|
||||||
|
|
||||||
raise exc.SizeLimitExceededException(
|
|
||||||
field_name,
|
field_name,
|
||||||
size_kb,
|
size_kb,
|
||||||
size_limit_kb
|
size_limit_kb
|
||||||
)
|
)
|
||||||
|
|
||||||
|
LOG.error(msg)
|
||||||
|
|
||||||
|
raise exc.SizeLimitExceededException(msg)
|
||||||
|
|
||||||
|
|
||||||
def register_length_validator(attr_name):
|
def register_length_validator(attr_name):
|
||||||
"""Register an event listener on the attribute.
|
"""Register an event listener on the attribute.
|
||||||
|
@ -185,11 +185,6 @@ class InvalidResultException(MistralException):
|
|||||||
class SizeLimitExceededException(MistralException):
|
class SizeLimitExceededException(MistralException):
|
||||||
http_code = 400
|
http_code = 400
|
||||||
|
|
||||||
def __init__(self, field_name, size_kb, size_limit_kb):
|
|
||||||
super(SizeLimitExceededException, self).__init__(
|
|
||||||
"Size of '%s' is %dKB which exceeds the limit of %dKB"
|
|
||||||
% (field_name, size_kb, size_limit_kb))
|
|
||||||
|
|
||||||
|
|
||||||
class CoordinationException(MistralException):
|
class CoordinationException(MistralException):
|
||||||
http_code = 500
|
http_code = 500
|
||||||
|
@ -85,25 +85,31 @@ def _wrap_exception_and_reraise(exception):
|
|||||||
|
|
||||||
|
|
||||||
def wrap_messaging_exception(method):
|
def wrap_messaging_exception(method):
|
||||||
"""This decorator unwrap remote error in one of MistralException.
|
"""The decorator unwraps a remote error into one of the mistral exceptions.
|
||||||
|
|
||||||
oslo.messaging has different behavior on raising exceptions
|
oslo.messaging has different behavior on raising exceptions depending on
|
||||||
when fake or rabbit transports are used. In case of rabbit
|
whether we use 'fake' or 'rabbit' transports. In case of 'rabbit' transport
|
||||||
transport it raises wrapped RemoteError which forwards directly
|
it raises an instance of RemoteError which forwards directly to the API.
|
||||||
to API. Wrapped RemoteError contains one of MistralException raised
|
The RemoteError instance contains one of the MistralException instances
|
||||||
remotely on Engine and for correct exception interpretation we
|
raised remotely on the RPC server side and for correct exception handling
|
||||||
need to unwrap and raise given exception and manually send it to
|
we need to unwrap and raise the original wrapped exception.
|
||||||
API layer.
|
|
||||||
"""
|
"""
|
||||||
def decorator(*args, **kwargs):
|
def decorator(*args, **kwargs):
|
||||||
try:
|
try:
|
||||||
return method(*args, **kwargs)
|
return method(*args, **kwargs)
|
||||||
|
|
||||||
except exc.MistralException:
|
except exc.MistralException:
|
||||||
raise
|
raise
|
||||||
except (client.RemoteError, exc.KombuException, Exception) as e:
|
except (client.RemoteError, exc.KombuException, Exception) as e:
|
||||||
|
# Since we're going to transform the original exception
|
||||||
|
# we need to log it as is.
|
||||||
|
LOG.exception(
|
||||||
|
"Caught a messaging remote error."
|
||||||
|
" See details of the original exception."
|
||||||
|
)
|
||||||
|
|
||||||
if hasattr(e, 'exc_type') and hasattr(exc, e.exc_type):
|
if hasattr(e, 'exc_type') and hasattr(exc, e.exc_type):
|
||||||
exc_cls = getattr(exc, e.exc_type)
|
exc_cls = getattr(exc, e.exc_type)
|
||||||
|
|
||||||
raise exc_cls(e.value)
|
raise exc_cls(e.value)
|
||||||
|
|
||||||
_wrap_exception_and_reraise(e)
|
_wrap_exception_and_reraise(e)
|
||||||
|
@ -140,7 +140,8 @@ class ExecutionFieldsSizeLimitTest(base.EngineTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"Size of 'input' is 1KB which exceeds the limit of 0KB",
|
'Field size limit exceeded'
|
||||||
|
' [class=TaskExecution, field=input, size=1KB, limit=0KB]',
|
||||||
str(e)
|
str(e)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -156,7 +157,8 @@ class ExecutionFieldsSizeLimitTest(base.EngineTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
"Size of 'input' is 1KB which exceeds the limit of 0KB",
|
'Field size limit exceeded'
|
||||||
|
' [class=TaskExecution, field=input, size=1KB, limit=0KB]',
|
||||||
str(e)
|
str(e)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -170,7 +172,8 @@ class ExecutionFieldsSizeLimitTest(base.EngineTestCase):
|
|||||||
|
|
||||||
self.assertEqual(states.ERROR, wf_ex.state)
|
self.assertEqual(states.ERROR, wf_ex.state)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"Size of 'input' is 1KB which exceeds the limit of 0KB",
|
"Field size limit exceeded"
|
||||||
|
" [class=TaskExecution, field=input, size=1KB, limit=0KB]",
|
||||||
wf_ex.state_info
|
wf_ex.state_info
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -189,7 +192,8 @@ class ExecutionFieldsSizeLimitTest(base.EngineTestCase):
|
|||||||
wf_ex = db_api.get_workflow_execution(wf_ex.id)
|
wf_ex = db_api.get_workflow_execution(wf_ex.id)
|
||||||
|
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"Size of 'output' is 1KB which exceeds the limit of 0KB",
|
'Field size limit exceeded'
|
||||||
|
' [class=TaskExecution, field=output, size=1KB, limit=0KB]',
|
||||||
wf_ex.state_info
|
wf_ex.state_info
|
||||||
)
|
)
|
||||||
self.assertEqual(states.ERROR, wf_ex.state)
|
self.assertEqual(states.ERROR, wf_ex.state)
|
||||||
@ -211,7 +215,7 @@ class ExecutionFieldsSizeLimitTest(base.EngineTestCase):
|
|||||||
task_execs = wf_ex.task_executions
|
task_execs = wf_ex.task_executions
|
||||||
|
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
'Failed to handle action completion [error=Size of',
|
'Failed to handle action completion [error=Field size',
|
||||||
wf_ex.state_info
|
wf_ex.state_info
|
||||||
)
|
)
|
||||||
self.assertIn('wf=wf, task=task1', wf_ex.state_info)
|
self.assertIn('wf=wf, task=task1', wf_ex.state_info)
|
||||||
@ -219,7 +223,8 @@ class ExecutionFieldsSizeLimitTest(base.EngineTestCase):
|
|||||||
task_ex = self._assert_single_item(task_execs, name='task1')
|
task_ex = self._assert_single_item(task_execs, name='task1')
|
||||||
|
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"Size of 'published' is 1KB which exceeds the limit of 0KB",
|
'Field size limit exceeded'
|
||||||
|
' [class=TaskExecution, field=published, size=1KB, limit=0KB]',
|
||||||
task_ex.state_info
|
task_ex.state_info
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -237,7 +242,8 @@ class ExecutionFieldsSizeLimitTest(base.EngineTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"Size of 'params' is 1KB which exceeds the limit of 0KB",
|
'Field size limit exceeded'
|
||||||
|
' [class=TaskExecution, field=params, size=1KB, limit=0KB]',
|
||||||
str(e)
|
str(e)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user