deb-glance/glance/async/utils.py
Joshua Harlow 8b6b943635 Add note in comment where upstream taskflow change is
The optional task should in the future not be needed
due to an ongoing taskflow review, so denote that in
the async code for future prosperity.

Change-Id: I96ac9c59c10cd61d48aee609150271c72572be7f
2016-01-25 12:29:16 -08:00

70 lines
2.9 KiB
Python

# Copyright 2015 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
from oslo_utils import encodeutils
from taskflow import task
from glance.i18n import _LW
LOG = logging.getLogger(__name__)
class OptionalTask(task.Task):
def __init__(self, *args, **kwargs):
super(OptionalTask, self).__init__(*args, **kwargs)
self.execute = self._catch_all(self.execute)
def _catch_all(self, func):
# NOTE(flaper87): Read this comment before calling the MI6
# Here's the thing, there's no nice way to define "optional"
# tasks. That is, tasks whose failure shouldn't affect the execution
# of the flow. The only current "sane" way to do this, is by catching
# everything and logging. This seems harmless from a taskflow
# perspective but it is not. There are some issues related to this
# "workaround":
#
# - Task's states will shamelessly lie to us saying the task succeeded.
#
# - No revert procedure will be triggered, which means optional tasks,
# for now, mustn't cause any side-effects because they won't be able to
# clean them up. If these tasks depend on other task that do cause side
# effects, a task that cleans those side effects most be registered as
# well. For example, _ImportToFS, _MyDumbTask, _DeleteFromFS.
#
# - Ideally, optional tasks shouldn't `provide` new values unless they
# are part of an optional flow. Due to the decoration of the execute
# method, these tasks will need to define the provided methods at
# class level using `default_provides`.
#
#
# The taskflow team is working on improving this and on something that
# will provide the ability of defining optional tasks. For now, to lie
# ourselves we must.
#
# NOTE(harlowja): The upstream change that is hopefully going to make
# this easier/built-in is at: https://review.openstack.org/#/c/271116/
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as exc:
msg = (_LW("An optional task has failed, "
"the failure was: %s") %
encodeutils.exception_to_unicode(exc))
LOG.warn(msg)
return wrapper