diff --git a/doc/source/atoms.rst b/doc/source/atoms.rst index d29c553c5..c54eb5710 100644 --- a/doc/source/atoms.rst +++ b/doc/source/atoms.rst @@ -58,20 +58,11 @@ associated `scope`_). Currently derivatives of the :py:class:`retry <taskflow.retry.Retry>` base class must provide a :py:func:`~taskflow.retry.Retry.on_failure` method to -determine how a failure should be handled. +determine how a failure should be handled. The current enumeration(s) that can +be returned from the :py:func:`~taskflow.retry.Retry.on_failure` method +are defined in an enumeration class described here: -The current enumeration set that can be returned from this method is: - -* ``RETRY`` - retries the surrounding subflow (a retry object is associated - with a flow, which is typically converted into a graph hierarchy at - compilation time) again. - -* ``REVERT`` - reverts only the surrounding subflow but *consult* the - parent atom before doing this to determine if the parent retry object - provides a different reconciliation strategy (retry atoms can be nested, this - is possible since flows themselves can be nested). - -* ``REVERT_ALL`` - completely reverts a whole flow. +.. autoclass:: taskflow.retry.Decision To aid in the reconciliation process the :py:class:`retry <taskflow.retry.Retry>` base class also mandates @@ -177,7 +168,13 @@ Interfaces ========== .. automodule:: taskflow.task -.. automodule:: taskflow.retry +.. autoclass:: taskflow.retry.Retry +.. autoclass:: taskflow.retry.History +.. autoclass:: taskflow.retry.AlwaysRevert +.. autoclass:: taskflow.retry.AlwaysRevertAll +.. autoclass:: taskflow.retry.Times +.. autoclass:: taskflow.retry.ForEach +.. autoclass:: taskflow.retry.ParameterizedForEach Hierarchy ========= @@ -185,5 +182,10 @@ Hierarchy .. inheritance-diagram:: taskflow.atom taskflow.task - taskflow.retry + taskflow.retry.Retry + taskflow.retry.AlwaysRevert + taskflow.retry.AlwaysRevertAll + taskflow.retry.Times + taskflow.retry.ForEach + taskflow.retry.ParameterizedForEach :parts: 1 diff --git a/requirements-py2.txt b/requirements-py2.txt index 3f1f97294..55d18ac09 100644 --- a/requirements-py2.txt +++ b/requirements-py2.txt @@ -13,6 +13,9 @@ ordereddict # Python 2->3 compatibility library. six>=1.9.0 +# Enum library made for <= python 3.3 +enum34 + # Very nice graph library networkx>=1.8 diff --git a/requirements-py3.txt b/requirements-py3.txt index 6809a0138..326ca311e 100644 --- a/requirements-py3.txt +++ b/requirements-py3.txt @@ -10,6 +10,9 @@ pbr>=0.6,!=0.7,<1.0 # Python 2->3 compatibility library. six>=1.9.0 +# Enum library made for <= python 3.3 +enum34 + # Very nice graph library networkx>=1.8 diff --git a/taskflow/retry.py b/taskflow/retry.py index 47ed8ca59..b7135a923 100644 --- a/taskflow/retry.py +++ b/taskflow/retry.py @@ -17,16 +17,38 @@ import abc +import enum import six from taskflow import atom from taskflow import exceptions as exc from taskflow.utils import misc -# Decision results. -REVERT = "REVERT" -REVERT_ALL = "REVERT_ALL" -RETRY = "RETRY" + +@enum.unique +class Decision(misc.StrEnum): + """Decision results/strategy enumeration.""" + + REVERT = "REVERT" + """Reverts only the surrounding/associated subflow. + + This strategy first consults the parent atom before reverting the + associated subflow to determine if the parent retry object provides a + different reconciliation strategy (if no parent retry object exists + then reverting will proceed, if one does exist the parent retry may + override this reconciliation strategy with its own). + """ + + #: Completely reverts the whole flow. + REVERT_ALL = "REVERT_ALL" + + #: Retries the surrounding/associated subflow again. + RETRY = "RETRY" + +# Retain these aliases for a number of releases... +REVERT = Decision.REVERT +REVERT_ALL = Decision.REVERT_ALL +RETRY = Decision.RETRY # Constants passed into revert/execute kwargs. # @@ -108,14 +130,16 @@ class Retry(atom.Atom): This abstract base class is used to inherit from and provide different strategies that will be activated upon execution failures. Since a retry - object is an atom it may also provide :meth:`.execute` and - :meth:`.revert` methods to alter the inputs of connected atoms (depending - on the desired strategy to be used this can be quite useful). + object is an atom it may also provide :meth:`~taskflow.retry.Retry.execute` + and :meth:`~taskflow.retry.Retry.revert` methods to alter the inputs of + connected atoms (depending on the desired strategy to be used this can be + quite useful). - NOTE(harlowja): the :meth:`.execute` and :meth:`.revert` and - :meth:`.on_failure` will automatically be given a ``history`` parameter, - which contains information about the past decisions and outcomes - that have occurred (if available). + NOTE(harlowja): the :meth:`~taskflow.retry.Retry.execute` and + :meth:`~taskflow.retry.Retry.revert` and + :meth:`~taskflow.retry.Retry.on_failure` will automatically be given + a ``history`` parameter, which contains information about the past + decisions and outcomes that have occurred (if available). """ default_provides = None diff --git a/taskflow/utils/misc.py b/taskflow/utils/misc.py index b2e967d44..daac38559 100644 --- a/taskflow/utils/misc.py +++ b/taskflow/utils/misc.py @@ -26,6 +26,7 @@ import threading import time import types +import enum from oslo_serialization import jsonutils from oslo_utils import importutils from oslo_utils import netutils @@ -57,6 +58,17 @@ _MONOTONIC_LOCATIONS = tuple([ ]) +class StrEnum(str, enum.Enum): + """An enumeration that is also a string and can be compared to strings.""" + + def __new__(cls, *args, **kwargs): + for a in args: + if not isinstance(a, str): + raise TypeError("Enumeration '%s' (%s) is not" + " a string" % (a, type(a).__name__)) + return super(StrEnum, cls).__new__(cls, *args, **kwargs) + + def find_monotonic(allow_time_time=False): """Tries to find a monotonic time providing function (and returns it).""" for import_str in _MONOTONIC_LOCATIONS: