Merge "Make unspecified periodic spaced tasks run on default interval"
This commit is contained in:
@@ -44,8 +44,8 @@ def periodic_task(*args, **kwargs):
|
|||||||
|
|
||||||
This decorator can be used in two ways:
|
This decorator can be used in two ways:
|
||||||
|
|
||||||
1. Without arguments '@periodic_task', this will be run on every cycle
|
1. Without arguments '@periodic_task', this will be run on the default
|
||||||
of the periodic scheduler.
|
interval of 60 seconds.
|
||||||
|
|
||||||
2. With arguments:
|
2. With arguments:
|
||||||
@periodic_task(spacing=N [, run_immediately=[True|False]])
|
@periodic_task(spacing=N [, run_immediately=[True|False]])
|
||||||
@@ -133,9 +133,10 @@ class _PeriodicTasksMeta(type):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# A periodic spacing of zero indicates that this task should
|
# A periodic spacing of zero indicates that this task should
|
||||||
# be run every pass
|
# be run on the default interval to avoid running too
|
||||||
|
# frequently.
|
||||||
if task._periodic_spacing == 0:
|
if task._periodic_spacing == 0:
|
||||||
task._periodic_spacing = None
|
task._periodic_spacing = DEFAULT_INTERVAL
|
||||||
|
|
||||||
cls._periodic_tasks.append((name, task))
|
cls._periodic_tasks.append((name, task))
|
||||||
cls._periodic_spacing[name] = task._periodic_spacing
|
cls._periodic_spacing[name] = task._periodic_spacing
|
||||||
@@ -159,13 +160,12 @@ class PeriodicTasks(object):
|
|||||||
last_run = self._periodic_last_run[task_name]
|
last_run = self._periodic_last_run[task_name]
|
||||||
|
|
||||||
# If a periodic task is _nearly_ due, then we'll run it early
|
# If a periodic task is _nearly_ due, then we'll run it early
|
||||||
if spacing is not None:
|
idle_for = min(idle_for, spacing)
|
||||||
idle_for = min(idle_for, spacing)
|
if last_run is not None:
|
||||||
if last_run is not None:
|
delta = last_run + spacing - time.time()
|
||||||
delta = last_run + spacing - time.time()
|
if delta > 0.2:
|
||||||
if delta > 0.2:
|
idle_for = min(idle_for, delta)
|
||||||
idle_for = min(idle_for, delta)
|
continue
|
||||||
continue
|
|
||||||
|
|
||||||
LOG.debug("Running periodic task %(full_task_name)s",
|
LOG.debug("Running periodic task %(full_task_name)s",
|
||||||
{"full_task_name": full_task_name})
|
{"full_task_name": full_task_name})
|
||||||
|
|||||||
@@ -45,11 +45,12 @@ class AService(periodic_task.PeriodicTasks):
|
|||||||
self.called['urg'] += 1
|
self.called['urg'] += 1
|
||||||
raise AnException('urg')
|
raise AnException('urg')
|
||||||
|
|
||||||
@periodic_task.periodic_task(spacing=10, run_immediately=True)
|
@periodic_task.periodic_task(spacing=10 + periodic_task.DEFAULT_INTERVAL,
|
||||||
|
run_immediately=True)
|
||||||
def doit_with_ticks(self, context):
|
def doit_with_ticks(self, context):
|
||||||
self.called['ticks'] += 1
|
self.called['ticks'] += 1
|
||||||
|
|
||||||
@periodic_task.periodic_task(spacing=10)
|
@periodic_task.periodic_task(spacing=10 + periodic_task.DEFAULT_INTERVAL)
|
||||||
def doit_with_tocks(self, context):
|
def doit_with_tocks(self, context):
|
||||||
self.called['tocks'] += 1
|
self.called['tocks'] += 1
|
||||||
|
|
||||||
@@ -62,31 +63,41 @@ class PeriodicTasksTestCase(test_base.BaseTestCase):
|
|||||||
serv = AService()
|
serv = AService()
|
||||||
now = serv._periodic_last_run['doit_with_tocks']
|
now = serv._periodic_last_run['doit_with_tocks']
|
||||||
|
|
||||||
mock_time.return_value = now
|
time = now + periodic_task.DEFAULT_INTERVAL
|
||||||
|
mock_time.return_value = time
|
||||||
serv.run_periodic_tasks(None)
|
serv.run_periodic_tasks(None)
|
||||||
self.assertEqual(serv.called['doit'], 1)
|
self.assertEqual(serv.called['doit'], 1)
|
||||||
self.assertEqual(serv.called['urg'], 1)
|
self.assertEqual(serv.called['urg'], 1)
|
||||||
self.assertEqual(serv.called['ticks'], 1)
|
self.assertEqual(serv.called['ticks'], 1)
|
||||||
self.assertEqual(serv.called['tocks'], 0)
|
self.assertEqual(serv.called['tocks'], 0)
|
||||||
|
|
||||||
mock_time.return_value = now + 9
|
time = time + 9 + periodic_task.DEFAULT_INTERVAL
|
||||||
|
mock_time.return_value = time
|
||||||
serv.run_periodic_tasks(None)
|
serv.run_periodic_tasks(None)
|
||||||
self.assertEqual(serv.called['doit'], 2)
|
self.assertEqual(serv.called['doit'], 2)
|
||||||
self.assertEqual(serv.called['urg'], 2)
|
self.assertEqual(serv.called['urg'], 2)
|
||||||
# doit_with_ticks will only be called the first time because its
|
# doit_with_ticks will only be called the first time because its
|
||||||
# spacing time interval will not have elapsed between the calls.
|
# spacing time interval will not have elapsed between the calls.
|
||||||
self.assertEqual(serv.called['ticks'], 1)
|
self.assertEqual(serv.called['ticks'], 1)
|
||||||
self.assertEqual(serv.called['tocks'], 0)
|
# doit_with_tocks will run since idle_for is equal to DEFAULT_INTERVAL
|
||||||
|
# and the task processor will pick the minimum of those two to
|
||||||
|
# determine when to run, and the idle time will have passed.
|
||||||
|
self.assertEqual(serv.called['tocks'], 1)
|
||||||
|
|
||||||
mock_time.return_value = now + 10
|
time = time + 10 + periodic_task.DEFAULT_INTERVAL
|
||||||
|
mock_time.return_value = time
|
||||||
serv.run_periodic_tasks(None)
|
serv.run_periodic_tasks(None)
|
||||||
self.assertEqual(serv.called['doit'], 3)
|
self.assertEqual(serv.called['doit'], 3)
|
||||||
self.assertEqual(serv.called['urg'], 3)
|
self.assertEqual(serv.called['urg'], 3)
|
||||||
self.assertEqual(serv.called['ticks'], 2)
|
self.assertEqual(serv.called['ticks'], 2)
|
||||||
self.assertEqual(serv.called['tocks'], 1)
|
self.assertEqual(serv.called['tocks'], 2)
|
||||||
|
|
||||||
def test_raises(self):
|
@mock.patch('time.time')
|
||||||
|
def test_raises(self, mock_time):
|
||||||
serv = AService()
|
serv = AService()
|
||||||
|
now = serv._periodic_last_run['crashit']
|
||||||
|
|
||||||
|
mock_time.return_value = now + periodic_task.DEFAULT_INTERVAL
|
||||||
self.assertRaises(AnException,
|
self.assertRaises(AnException,
|
||||||
serv.run_periodic_tasks,
|
serv.run_periodic_tasks,
|
||||||
None, raise_on_error=True)
|
None, raise_on_error=True)
|
||||||
@@ -113,7 +124,8 @@ class ManagerMetaTestCase(test_base.BaseTestCase):
|
|||||||
|
|
||||||
m = Manager()
|
m = Manager()
|
||||||
self.assertThat(m._periodic_tasks, matchers.HasLength(2))
|
self.assertThat(m._periodic_tasks, matchers.HasLength(2))
|
||||||
self.assertIsNone(m._periodic_spacing['foo'])
|
self.assertEqual(periodic_task.DEFAULT_INTERVAL,
|
||||||
|
m._periodic_spacing['foo'])
|
||||||
self.assertEqual(4, m._periodic_spacing['bar'])
|
self.assertEqual(4, m._periodic_spacing['bar'])
|
||||||
self.assertThat(
|
self.assertThat(
|
||||||
m._periodic_spacing, matchers.Not(matchers.Contains('baz')))
|
m._periodic_spacing, matchers.Not(matchers.Contains('baz')))
|
||||||
|
|||||||
Reference in New Issue
Block a user