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:
parent
7076774bb2
commit
d05e086b8d
@ -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.
|
||||
|
||||
|
@ -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):
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Add a new type of looping call: FixedIntervalWithTimeoutLoopingCall. It is
|
||||
a FixedIntervalLoopingCall with timeout checking.
|
Loading…
Reference in New Issue
Block a user