Add FixedIntervalWithTimeoutLoopingCall

Currently when using FixedIntervalLoopingCall, folks need to
add timeout checking logic in their function if they need it.
Adding a new class FixedIntervalWithTimeoutLoopingCall to
provide timeout checking support will save those effort.

Change-Id: I78bfb9e259c2394137d7efbc0ee96bb18a6dc5e7
This commit is contained in:
Wenzhi Yu 2016-10-31 16:25:48 +08:00
parent 7076774bb2
commit d05e086b8d
3 changed files with 46 additions and 0 deletions

View File

@ -17,6 +17,7 @@
import random
import sys
import time
from eventlet import event
from eventlet import greenthread
@ -180,6 +181,37 @@ class FixedIntervalLoopingCall(LoopingCallBase):
stop_on_exception=stop_on_exception)
class FixedIntervalWithTimeoutLoopingCall(LoopingCallBase):
"""A fixed interval looping call with timeout checking mechanism."""
_RUN_ONLY_ONE_MESSAGE = _("A fixed interval looping call with timeout"
" checking and can only run one function at"
" at a time")
_KIND = _('Fixed interval looping call with timeout checking.')
def start(self, interval, initial_delay=None,
stop_on_exception=True, timeout=0):
start_time = time.time()
def _idle_for(result, elapsed):
delay = round(elapsed - interval, 2)
if delay > 0:
func_name = reflection.get_callable_name(self.f)
LOG.warning(_LW('Function %(func_name)r run outlasted '
'interval by %(delay).2f sec'),
{'func_name': func_name, 'delay': delay})
elapsed_time = time.time() - start_time
if timeout > 0 and elapsed_time > timeout:
raise LoopingCallTimeOut(
_('Looping call timed out after %.02f seconds')
% elapsed_time)
return -delay if delay < 0 else 0
return self._start(_idle_for, initial_delay=initial_delay,
stop_on_exception=stop_on_exception)
class DynamicLoopingCall(LoopingCallBase):
"""A looping call which sleeps until the next known event.

View File

@ -180,6 +180,15 @@ class LoopingCallTestCase(test_base.BaseTestCase):
(i, expected, actual))
self.assertAlmostEqual(expected, actual, message=message)
def test_looping_call_timed_out(self):
def _fake_task():
pass
timer = loopingcall.FixedIntervalWithTimeoutLoopingCall(_fake_task)
self.assertRaises(loopingcall.LoopingCallTimeOut,
timer.start(interval=0.1, timeout=0.3).wait)
class DynamicLoopingCallTestCase(test_base.BaseTestCase):
def setUp(self):

View File

@ -0,0 +1,5 @@
---
features:
- |
Add a new type of looping call: FixedIntervalWithTimeoutLoopingCall. It is
a FixedIntervalLoopingCall with timeout checking.