Handling corner cases in dynamic looping call
If the periodic task for dynamic looping call returns no suggestion for delay, then we should use periodic_interval_max. If periodic_interval_max is not specified, we should raise RuntimeError. Otherwise, passing 'None' as a value, causes Exception at eventlet's sleep() call. Change-Id: Ida3e75bc64132d6b5920fa94657aa962e2fe9f53 Closes-bug: #1489998
This commit is contained in:
parent
c2fd269772
commit
fad5b04d59
@ -166,6 +166,10 @@ class DynamicLoopingCall(LoopingCallBase):
|
|||||||
|
|
||||||
_RUN_ONLY_ONE_MESSAGE = _("A dynamic interval looping call can only run"
|
_RUN_ONLY_ONE_MESSAGE = _("A dynamic interval looping call can only run"
|
||||||
" one function at a time")
|
" one function at a time")
|
||||||
|
_TASK_MISSING_SLEEP_VALUE_MESSAGE = _(
|
||||||
|
"A dynamic interval looping call should supply either an"
|
||||||
|
" interval or periodic_interval_max"
|
||||||
|
)
|
||||||
|
|
||||||
_KIND = _('Dynamic interval looping call')
|
_KIND = _('Dynamic interval looping call')
|
||||||
|
|
||||||
@ -173,9 +177,20 @@ class DynamicLoopingCall(LoopingCallBase):
|
|||||||
stop_on_exception=True):
|
stop_on_exception=True):
|
||||||
def _idle_for(suggested_delay, elapsed):
|
def _idle_for(suggested_delay, elapsed):
|
||||||
delay = suggested_delay
|
delay = suggested_delay
|
||||||
if periodic_interval_max is not None:
|
if delay is None:
|
||||||
delay = min(delay, periodic_interval_max)
|
if periodic_interval_max is not None:
|
||||||
|
delay = periodic_interval_max
|
||||||
|
else:
|
||||||
|
# Note(suro-patz): An application used to receive a
|
||||||
|
# TypeError thrown from eventlet layer, before
|
||||||
|
# this RuntimeError was introduced.
|
||||||
|
raise RuntimeError(
|
||||||
|
self._TASK_MISSING_SLEEP_VALUE_MESSAGE)
|
||||||
|
else:
|
||||||
|
if periodic_interval_max is not None:
|
||||||
|
delay = min(delay, periodic_interval_max)
|
||||||
return delay
|
return delay
|
||||||
|
|
||||||
return self._start(_idle_for, initial_delay=initial_delay,
|
return self._start(_idle_for, initial_delay=initial_delay,
|
||||||
stop_on_exception=stop_on_exception)
|
stop_on_exception=stop_on_exception)
|
||||||
|
|
||||||
|
@ -192,6 +192,30 @@ class DynamicLoopingCallTestCase(test_base.BaseTestCase):
|
|||||||
timer = loopingcall.DynamicLoopingCall(self._wait_for_zero)
|
timer = loopingcall.DynamicLoopingCall(self._wait_for_zero)
|
||||||
self.assertFalse(timer.start().wait())
|
self.assertFalse(timer.start().wait())
|
||||||
|
|
||||||
|
def _timeout_task_without_any_return(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_timeout_task_without_return_and_max_periodic(self):
|
||||||
|
timer = loopingcall.DynamicLoopingCall(
|
||||||
|
self._timeout_task_without_any_return
|
||||||
|
)
|
||||||
|
self.assertRaises(RuntimeError, timer.start().wait)
|
||||||
|
|
||||||
|
def _timeout_task_without_return_but_with_done(self):
|
||||||
|
if self.num_runs == 0:
|
||||||
|
raise loopingcall.LoopingCallDone(False)
|
||||||
|
else:
|
||||||
|
self.num_runs = self.num_runs - 1
|
||||||
|
|
||||||
|
@mock.patch('eventlet.greenthread.sleep')
|
||||||
|
def test_timeout_task_without_return(self, sleep_mock):
|
||||||
|
self.num_runs = 1
|
||||||
|
timer = loopingcall.DynamicLoopingCall(
|
||||||
|
self._timeout_task_without_return_but_with_done
|
||||||
|
)
|
||||||
|
timer.start(periodic_interval_max=5).wait()
|
||||||
|
sleep_mock.assert_has_calls([mock.call(5)])
|
||||||
|
|
||||||
@mock.patch('eventlet.greenthread.sleep')
|
@mock.patch('eventlet.greenthread.sleep')
|
||||||
def test_interval_adjustment(self, sleep_mock):
|
def test_interval_adjustment(self, sleep_mock):
|
||||||
self.num_runs = 2
|
self.num_runs = 2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user