Refactor/reduce shared 'ensure(task/retry)' code

These methods are nearly identical so we should refactor
them to use the same code for sanity and understanding
purposes.

Change-Id: Ibaf270bd451b6d02d7782901bc2327afe04d3847
This commit is contained in:
Joshua Harlow
2015-04-02 11:15:06 -07:00
committed by Joshua Harlow
parent 426d08f951
commit 530328a86c
2 changed files with 40 additions and 62 deletions

View File

@@ -152,8 +152,8 @@ class Storage(object):
self._injected_args = {} self._injected_args = {}
self._lock = lock_utils.ReaderWriterLock() self._lock = lock_utils.ReaderWriterLock()
self._ensure_matchers = [ self._ensure_matchers = [
((task.BaseTask,), self._ensure_task), ((task.BaseTask,), (logbook.TaskDetail, 'Task')),
((retry.Retry,), self._ensure_retry), ((retry.Retry,), (logbook.RetryDetail, 'Retry')),
] ]
if scope_fetcher is None: if scope_fetcher is None:
scope_fetcher = lambda atom_name: None scope_fetcher = lambda atom_name: None
@@ -191,73 +191,47 @@ class Storage(object):
Returns uuid for the atomdetail that is/was created. Returns uuid for the atomdetail that is/was created.
""" """
functor = misc.match_type_handler(atom, self._ensure_matchers) match = misc.match_type(atom, self._ensure_matchers)
if not functor: if not match:
raise TypeError("Unknown item '%s' (%s) requested to ensure" raise TypeError("Unknown atom '%s' (%s) requested to ensure"
% (atom, type(atom))) % (atom, type(atom)))
else: else:
return functor(atom.name, detail_cls, kind = match
misc.get_version_string(atom), atom_id = self._ensure_atom_detail(kind, detail_cls, atom.name,
atom.save_as) misc.get_version_string(atom),
atom.save_as)
return atom_id
def _ensure_task(self, task_name, task_version, result_mapping): def _ensure_atom_detail(self, kind, detail_cls,
"""Ensures there is a taskdetail that corresponds to the task info. atom_name, atom_version, result_mapping):
"""Ensures there is a atomdetail that corresponds to the given atom.
If task does not exist, adds a record for it. Added task will have If atom does not exist, adds a record for it. Added atom will have
PENDING state. Sets result mapping for the task from result_mapping PENDING state. Sets result mapping for the atom from result_mapping
argument. argument.
Returns uuid for the task details corresponding to the task with Returns uuid for the atomdetails corresponding to the atom with
given name. given name.
""" """
if not task_name: if not atom_name:
raise ValueError("Task name must be non-empty") raise ValueError("%s name must be non-empty" % (kind))
with self._lock.write_lock(): with self._lock.write_lock():
try: try:
task_id = self._atom_name_to_uuid[task_name] atom_id = self._atom_name_to_uuid[atom_name]
except KeyError: except KeyError:
task_id = uuidutils.generate_uuid() atom_id = uuidutils.generate_uuid()
self._create_atom_detail(logbook.TaskDetail, task_name, self._create_atom_detail(detail_cls, atom_name,
task_id, task_version) atom_id, atom_version=atom_version)
else: else:
ad = self._flowdetail.find(task_id) ad = self._flowdetail.find(atom_id)
if not isinstance(ad, logbook.TaskDetail): if not isinstance(ad, detail_cls):
raise exceptions.Duplicate( raise exceptions.Duplicate(
"Atom detail %s already exists in flow detail %s." % "Atom detail '%s' already exists in flow"
(task_name, self._flowdetail.name)) " detail '%s'" % (atom_name, self._flowdetail.name))
self._set_result_mapping(task_name, result_mapping) self._set_result_mapping(atom_name, result_mapping)
return task_id return atom_id
def _ensure_retry(self, retry_name, retry_version, result_mapping): def _create_atom_detail(self, detail_cls, name, uuid, atom_version=None):
"""Ensures there is a retrydetail that corresponds to the retry info.
If retry does not exist, adds a record for it. Added retry
will have PENDING state. Sets result mapping for the retry from
result_mapping argument. Initializes retry result as an empty
collections of results and failures history.
Returns uuid for the retry details corresponding to the retry
with given name.
"""
if not retry_name:
raise ValueError("Retry name must be non-empty")
with self._lock.write_lock():
try:
retry_id = self._atom_name_to_uuid[retry_name]
except KeyError:
retry_id = uuidutils.generate_uuid()
self._create_atom_detail(logbook.RetryDetail, retry_name,
retry_id, retry_version)
else:
ad = self._flowdetail.find(retry_id)
if not isinstance(ad, logbook.RetryDetail):
raise exceptions.Duplicate(
"Atom detail %s already exists in flow detail %s." %
(retry_name, self._flowdetail.name))
self._set_result_mapping(retry_name, result_mapping)
return retry_id
def _create_atom_detail(self, detail_cls, name, uuid, task_version=None):
"""Add the atom detail to flow detail. """Add the atom detail to flow detail.
Atom becomes known to storage by that name and uuid. Atom becomes known to storage by that name and uuid.
@@ -265,7 +239,7 @@ class Storage(object):
""" """
ad = detail_cls(name, uuid) ad = detail_cls(name, uuid)
ad.state = states.PENDING ad.state = states.PENDING
ad.version = task_version ad.version = atom_version
# Add the atom detail to the clone, which upon success will be # Add the atom detail to the clone, which upon success will be
# updated into the contained flow detail; if it does not get saved # updated into the contained flow detail; if it does not get saved
# then no update will happen. # then no update will happen.

View File

@@ -88,14 +88,18 @@ def find_monotonic(allow_time_time=False):
return None return None
def match_type_handler(item, type_handlers): def match_type(obj, matchers):
"""Matches a given items type using the given match types + handlers. """Matches a given object using the given matchers list/iterable.
Returns the handler if a type match occurs, otherwise none. NOTE(harlowja): each element of the provided list/iterable must be
tuple of (valid types, result).
Returns the result (the second element of the provided tuple) if a type
match occurs, otherwise none if no matches are found.
""" """
for (match_types, handler_func) in type_handlers: for (match_types, match_result) in matchers:
if isinstance(item, match_types): if isinstance(obj, match_types):
return handler_func return match_result
else: else:
return None return None