
To at least try to support things like windows it's better if we can make an attempt to use the platform neutral characters for line separator(s) where appropriate. Change-Id: Icc533ed4d4c94f461b7f19600b74146221f17b18
103 lines
4.0 KiB
Python
103 lines
4.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright (C) 2014 Yahoo! 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 __future__ import absolute_import
|
|
|
|
import logging
|
|
import os
|
|
|
|
import six
|
|
|
|
from taskflow import exceptions
|
|
from taskflow.listeners import base
|
|
from taskflow import states
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class CheckingClaimListener(base.Listener):
|
|
"""Listener that interacts [engine, job, jobboard]; ensures claim is valid.
|
|
|
|
This listener (or a derivative) can be associated with an engines
|
|
notification system after the job has been claimed (so that the jobs work
|
|
can be worked on by that engine). This listener (after associated) will
|
|
check that the job is still claimed *whenever* the engine notifies of a
|
|
task or flow state change. If the job is not claimed when a state change
|
|
occurs, a associated handler (or the default) will be activated to
|
|
determine how to react to this *hopefully* exceptional case.
|
|
|
|
NOTE(harlowja): this may create more traffic than desired to the
|
|
jobboard backend (zookeeper or other), since the amount of state change
|
|
per task and flow is non-zero (and checking during each state change will
|
|
result in quite a few calls to that management system to check the jobs
|
|
claim status); this could be later optimized to check less (or only check
|
|
on a smaller set of states)
|
|
|
|
NOTE(harlowja): if a custom ``on_job_loss`` callback is provided it must
|
|
accept three positional arguments, the first being the current engine being
|
|
ran, the second being the 'task/flow' state and the third being the details
|
|
that were sent from the engine to listeners for inspection.
|
|
"""
|
|
|
|
def __init__(self, engine, job, board, owner, on_job_loss=None):
|
|
super(CheckingClaimListener, self).__init__(engine)
|
|
self._job = job
|
|
self._board = board
|
|
self._owner = owner
|
|
if on_job_loss is None:
|
|
self._on_job_loss = self._suspend_engine_on_loss
|
|
else:
|
|
if not six.callable(on_job_loss):
|
|
raise ValueError("Custom 'on_job_loss' handler must be"
|
|
" callable")
|
|
self._on_job_loss = on_job_loss
|
|
|
|
def _suspend_engine_on_loss(self, engine, state, details):
|
|
"""The default strategy for handling claims being lost."""
|
|
try:
|
|
engine.suspend()
|
|
except exceptions.TaskFlowException as e:
|
|
LOG.warn("Failed suspending engine '%s', (previously owned by"
|
|
" '%s'):%s%s", engine, self._owner, os.linesep,
|
|
e.pformat())
|
|
|
|
def _flow_receiver(self, state, details):
|
|
self._claim_checker(state, details)
|
|
|
|
def _task_receiver(self, state, details):
|
|
self._claim_checker(state, details)
|
|
|
|
def _has_been_lost(self):
|
|
try:
|
|
job_state = self._job.state
|
|
job_owner = self._board.find_owner(self._job)
|
|
except (exceptions.NotFound, exceptions.JobFailure):
|
|
return True
|
|
else:
|
|
if job_state == states.UNCLAIMED or self._owner != job_owner:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def _claim_checker(self, state, details):
|
|
if not self._has_been_lost():
|
|
LOG.debug("Job '%s' is still claimed (actively owned by '%s')",
|
|
self._job, self._owner)
|
|
else:
|
|
LOG.warn("Job '%s' has lost its claim (previously owned by '%s')",
|
|
self._job, self._owner)
|
|
self._on_job_loss(self._engine, state, details)
|