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:
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
from eventlet import event
|
from eventlet import event
|
||||||
from eventlet import greenthread
|
from eventlet import greenthread
|
||||||
@@ -180,6 +181,37 @@ class FixedIntervalLoopingCall(LoopingCallBase):
|
|||||||
stop_on_exception=stop_on_exception)
|
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):
|
class DynamicLoopingCall(LoopingCallBase):
|
||||||
"""A looping call which sleeps until the next known event.
|
"""A looping call which sleeps until the next known event.
|
||||||
|
|
||||||
|
|||||||
@@ -180,6 +180,15 @@ class LoopingCallTestCase(test_base.BaseTestCase):
|
|||||||
(i, expected, actual))
|
(i, expected, actual))
|
||||||
self.assertAlmostEqual(expected, actual, message=message)
|
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):
|
class DynamicLoopingCallTestCase(test_base.BaseTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add a new type of looping call: FixedIntervalWithTimeoutLoopingCall. It is
|
||||||
|
a FixedIntervalLoopingCall with timeout checking.
|
||||||
Reference in New Issue
Block a user