summaryrefslogtreecommitdiff
path: root/taskflow/utils/persistence_utils.py
diff options
context:
space:
mode:
authorIvan A. Melnikov <imelnikov@griddynamics.com>2013-09-20 16:51:08 +0400
committerIvan A. Melnikov <imelnikov@griddynamics.com>2013-10-04 12:10:27 +0400
commit6134ff689a1d18a5ff23c3bb3fdcc140680f2387 (patch)
tree9eeccaeaa8f372d51a23f498c9dd7931f4c5cb4c /taskflow/utils/persistence_utils.py
parentcde0dee14e0e93018f5d9a5a32a98623ec29bbc4 (diff)
downloadtaskflow-6134ff689a1d18a5ff23c3bb3fdcc140680f2387.tar.gz
Wrapping and serializing failures
* save task failures to sqlalchemy backend and restore them from there; * for any wrapped exception use common WrappedFailre exception type, which makes it easier to handle particular exception types; * several minor improvements. Affects-db: this change adds db migration that looses exception information for saved task details. Change-Id: I575282002e6999646bbf51f492b82a7e3525787a
Diffstat (limited to 'taskflow/utils/persistence_utils.py')
-rw-r--r--taskflow/utils/persistence_utils.py42
1 files changed, 38 insertions, 4 deletions
diff --git a/taskflow/utils/persistence_utils.py b/taskflow/utils/persistence_utils.py
index 8f85050..63f7aea 100644
--- a/taskflow/utils/persistence_utils.py
+++ b/taskflow/utils/persistence_utils.py
@@ -22,6 +22,7 @@ import logging
from taskflow.openstack.common import uuidutils
from taskflow.persistence import logbook
+from taskflow.utils import misc
LOG = logging.getLogger(__name__)
@@ -111,10 +112,13 @@ def task_details_merge(td_e, td_new, deep_copy=False):
td_e.state = td_new.state
if td_e.results != td_new.results:
td_e.results = copy_fn(td_new.results)
- if td_e.exception != td_new.exception:
- td_e.exception = copy_fn(td_new.exception)
- if td_e.stacktrace != td_new.stacktrace:
- td_e.stacktrace = copy_fn(td_new.stacktrace)
+ if td_e.failure != td_new.failure:
+ # NOTE(imelnikov): we can't just deep copy Failures, as they
+ # contain tracebacks, which are not copyable.
+ if deep_copy:
+ td_e.failure = td_new.failure.copy()
+ else:
+ td_e.failure = td_new.failure
if td_e.meta != td_new.meta:
td_e.meta = copy_fn(td_new.meta)
return td_e
@@ -155,3 +159,33 @@ def logbook_merge(lb_e, lb_new, deep_copy=False):
if lb_e.meta != lb_new.meta:
lb_e.meta = copy_fn(lb_new.meta)
return lb_e
+
+
+def failure_to_dict(failure):
+ """Convert misc.Failure object to JSON-serializable dict"""
+ if not failure:
+ return None
+ if not isinstance(failure, misc.Failure):
+ raise TypeError('Failure object expected, but got %r'
+ % failure)
+ return {
+ 'exception_str': failure.exception_str,
+ 'traceback_str': failure.traceback_str,
+ 'exc_type_names': list(failure),
+ 'version': 1
+ }
+
+
+def failure_from_dict(data):
+ """Restore misc.Failure object from dict.
+
+ The dict should be similar to what failure_to_dict() function
+ produces.
+ """
+ if not data:
+ return None
+ version = data.pop('version', None)
+ if version != 1:
+ raise ValueError('Invalid version of saved Failure object: %r'
+ % version)
+ return misc.Failure(**data)