From 37b72ec7b5333b580d842b4e4dc6f1dacdc351b5 Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Tue, 17 Feb 2015 21:39:48 -0800 Subject: [PATCH] Use the enum library for the retry strategy enumerations Instead of having a set of string constants that are the retry strategy/decision result have it instead be an enumerator that can be more clearly associated in docs and in code that these values are explicitly the strategies that the retry code can use (making it more obvious to users of these constants what they are for). This also updates the retry docs to use this new linkable class when describing the various strategies that can be used/returned. Change-Id: I944e521562be26f5315d7553da8d5820fc284c49 --- doc/source/atoms.rst | 32 +++++++++++++++-------------- requirements-py2.txt | 3 +++ requirements-py3.txt | 3 +++ taskflow/retry.py | 46 ++++++++++++++++++++++++++++++++---------- taskflow/utils/misc.py | 12 +++++++++++ 5 files changed, 70 insertions(+), 26 deletions(-) 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 ` 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 ` 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 083caec03..a60be3821 100644 --- a/requirements-py2.txt +++ b/requirements-py2.txt @@ -13,6 +13,9 @@ ordereddict # Python 2->3 compatibility library. six>=1.7.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 b04fc0aff..a2ad2858b 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.7.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: