|
@@ -5,12 +5,18 @@ from datetime import datetime, timedelta
|
|
|
from celery import log
|
|
|
from celery import beat
|
|
|
from celery import conf
|
|
|
+from celery.task.base import Task
|
|
|
+from celery.schedules import schedule
|
|
|
from celery.utils import gen_unique_id
|
|
|
from celery.task.base import PeriodicTask
|
|
|
from celery.registry import TaskRegistry
|
|
|
from celery.result import AsyncResult
|
|
|
|
|
|
|
|
|
+class Object(object):
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
class MockShelve(dict):
|
|
|
closed = False
|
|
|
synced = False
|
|
@@ -22,7 +28,7 @@ class MockShelve(dict):
|
|
|
self.synced = True
|
|
|
|
|
|
|
|
|
-class MockClockService(object):
|
|
|
+class MockService(object):
|
|
|
started = False
|
|
|
stopped = False
|
|
|
|
|
@@ -36,177 +42,40 @@ class MockClockService(object):
|
|
|
self.stopped = True
|
|
|
|
|
|
|
|
|
-class DuePeriodicTask(PeriodicTask):
|
|
|
- run_every = timedelta(seconds=1)
|
|
|
- applied = False
|
|
|
-
|
|
|
- def is_due(self, *args, **kwargs):
|
|
|
- return True, 100
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def apply_async(self, *args, **kwargs):
|
|
|
- self.applied = True
|
|
|
- return AsyncResult(gen_unique_id())
|
|
|
-
|
|
|
-
|
|
|
-class DuePeriodicTaskRaising(PeriodicTask):
|
|
|
- run_every = timedelta(seconds=1)
|
|
|
- applied = False
|
|
|
-
|
|
|
- def is_due(self, *args, **kwargs):
|
|
|
- return True, 0
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def apply_async(self, *args, **kwargs):
|
|
|
- raise Exception("FoozBaaz")
|
|
|
-
|
|
|
-
|
|
|
-class PendingPeriodicTask(PeriodicTask):
|
|
|
- run_every = timedelta(seconds=1)
|
|
|
- applied = False
|
|
|
-
|
|
|
- def is_due(self, *args, **kwargs):
|
|
|
- return False, 100
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def apply_async(self, *args, **kwargs):
|
|
|
- self.applied = True
|
|
|
- return AsyncResult(gen_unique_id())
|
|
|
-
|
|
|
-
|
|
|
-class AdditionalTask(PeriodicTask):
|
|
|
- run_every = timedelta(days=7)
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def apply_async(self, *args, **kwargs):
|
|
|
- raise Exception("FoozBaaz")
|
|
|
-
|
|
|
|
|
|
-class TestScheduleEntry(unittest.TestCase):
|
|
|
-
|
|
|
- def test_constructor(self):
|
|
|
- s = beat.ScheduleEntry(DuePeriodicTask.name)
|
|
|
- self.assertEqual(s.name, DuePeriodicTask.name)
|
|
|
- self.assertIsInstance(s.last_run_at, datetime)
|
|
|
- self.assertEqual(s.total_run_count, 0)
|
|
|
-
|
|
|
- now = datetime.now()
|
|
|
- s = beat.ScheduleEntry(DuePeriodicTask.name, now, 300)
|
|
|
- self.assertEqual(s.name, DuePeriodicTask.name)
|
|
|
- self.assertEqual(s.last_run_at, now)
|
|
|
- self.assertEqual(s.total_run_count, 300)
|
|
|
-
|
|
|
- def test_next(self):
|
|
|
- s = beat.ScheduleEntry(DuePeriodicTask.name, None, 300)
|
|
|
- n = s.next()
|
|
|
- self.assertEqual(n.name, s.name)
|
|
|
- self.assertEqual(n.total_run_count, 301)
|
|
|
- self.assertGreater(n.last_run_at, s.last_run_at)
|
|
|
-
|
|
|
- def test_is_due(self):
|
|
|
- due = beat.ScheduleEntry(DuePeriodicTask.name)
|
|
|
- pending = beat.ScheduleEntry(PendingPeriodicTask.name)
|
|
|
-
|
|
|
- self.assertTrue(due.is_due(DuePeriodicTask())[0])
|
|
|
- self.assertFalse(pending.is_due(PendingPeriodicTask())[0])
|
|
|
-
|
|
|
-
|
|
|
-class TestScheduler(unittest.TestCase):
|
|
|
-
|
|
|
- def setUp(self):
|
|
|
- self.registry = TaskRegistry()
|
|
|
- self.registry.register(DuePeriodicTask)
|
|
|
- self.registry.register(PendingPeriodicTask)
|
|
|
- self.scheduler = beat.Scheduler(self.registry,
|
|
|
- max_interval=0.0001,
|
|
|
- logger=log.get_default_logger())
|
|
|
-
|
|
|
- def test_constructor(self):
|
|
|
- s = beat.Scheduler()
|
|
|
- self.assertIsInstance(s.registry, TaskRegistry)
|
|
|
- self.assertIsInstance(s.schedule, dict)
|
|
|
- self.assertIsInstance(s.logger, logging.Logger)
|
|
|
- self.assertEqual(s.max_interval, conf.CELERYBEAT_MAX_LOOP_INTERVAL)
|
|
|
-
|
|
|
- def test_cleanup(self):
|
|
|
- self.scheduler.schedule["fbz"] = beat.ScheduleEntry("fbz")
|
|
|
- self.scheduler.cleanup()
|
|
|
- self.assertNotIn("fbz", self.scheduler.schedule)
|
|
|
-
|
|
|
- def test_schedule_registry(self):
|
|
|
- self.registry.register(AdditionalTask)
|
|
|
- self.scheduler.schedule_registry()
|
|
|
- self.assertIn(AdditionalTask.name, self.scheduler.schedule)
|
|
|
-
|
|
|
- def test_apply_async(self):
|
|
|
- due_task = self.registry[DuePeriodicTask.name]
|
|
|
- self.scheduler.apply_async(self.scheduler[due_task.name])
|
|
|
- self.assertTrue(due_task.applied)
|
|
|
-
|
|
|
- def test_apply_async_raises_SchedulingError_on_error(self):
|
|
|
- self.registry.register(AdditionalTask)
|
|
|
- self.scheduler.schedule_registry()
|
|
|
- add_task = self.registry[AdditionalTask.name]
|
|
|
- self.assertRaises(beat.SchedulingError,
|
|
|
- self.scheduler.apply_async,
|
|
|
- self.scheduler[add_task.name])
|
|
|
-
|
|
|
- def test_is_due(self):
|
|
|
- due = self.scheduler[DuePeriodicTask.name]
|
|
|
- pending = self.scheduler[PendingPeriodicTask.name]
|
|
|
-
|
|
|
- self.assertTrue(self.scheduler.is_due(due)[0])
|
|
|
- self.assertFalse(self.scheduler.is_due(pending)[0])
|
|
|
-
|
|
|
- def test_tick(self):
|
|
|
- self.scheduler.schedule.pop(DuePeriodicTaskRaising.name, None)
|
|
|
- self.registry.pop(DuePeriodicTaskRaising.name, None)
|
|
|
- self.assertEqual(self.scheduler.tick(),
|
|
|
- self.scheduler.max_interval)
|
|
|
-
|
|
|
- def test_quick_schedulingerror(self):
|
|
|
- self.registry.register(DuePeriodicTaskRaising)
|
|
|
- self.scheduler.schedule_registry()
|
|
|
- self.assertEqual(self.scheduler.tick(),
|
|
|
- self.scheduler.max_interval)
|
|
|
-
|
|
|
-
|
|
|
-class TestClockService(unittest.TestCase):
|
|
|
+class test_Service(unittest.TestCase):
|
|
|
|
|
|
def test_start(self):
|
|
|
- s = beat.ClockService()
|
|
|
sh = MockShelve()
|
|
|
- s.open_schedule = lambda *a, **kw: sh
|
|
|
|
|
|
- self.assertIsInstance(s.schedule, dict)
|
|
|
+ class PersistentScheduler(beat.PersistentScheduler):
|
|
|
+ persistence = Object()
|
|
|
+ persistence.open = lambda *a, **kw: sh
|
|
|
+
|
|
|
+ s = beat.Service(scheduler_cls=PersistentScheduler)
|
|
|
self.assertIsInstance(s.schedule, dict)
|
|
|
self.assertIsInstance(s.scheduler, beat.Scheduler)
|
|
|
- self.assertIsInstance(s.scheduler, beat.Scheduler)
|
|
|
-
|
|
|
- self.assertIs(s.schedule, sh)
|
|
|
- self.assertIs(s._schedule, sh)
|
|
|
+ self.assertListEqual(s.schedule.keys(), sh.keys())
|
|
|
|
|
|
- s._in_sync = False
|
|
|
s.sync()
|
|
|
self.assertTrue(sh.closed)
|
|
|
self.assertTrue(sh.synced)
|
|
|
self.assertTrue(s._stopped.isSet())
|
|
|
s.sync()
|
|
|
-
|
|
|
s.stop(wait=False)
|
|
|
self.assertTrue(s._shutdown.isSet())
|
|
|
s.stop(wait=True)
|
|
|
self.assertTrue(s._shutdown.isSet())
|
|
|
|
|
|
|
|
|
-class TestEmbeddedClockService(unittest.TestCase):
|
|
|
+class TestEmbeddedService(unittest.TestCase):
|
|
|
|
|
|
def test_start_stop_process(self):
|
|
|
- s = beat.EmbeddedClockService()
|
|
|
+ s = beat.EmbeddedService()
|
|
|
from multiprocessing import Process
|
|
|
self.assertIsInstance(s, Process)
|
|
|
- self.assertIsInstance(s.clockservice, beat.ClockService)
|
|
|
- s.clockservice = MockClockService()
|
|
|
+ self.assertIsInstance(s.service, beat.Service)
|
|
|
+ s.service = MockService()
|
|
|
|
|
|
class _Popen(object):
|
|
|
terminated = False
|
|
@@ -215,22 +84,22 @@ class TestEmbeddedClockService(unittest.TestCase):
|
|
|
self.terminated = True
|
|
|
|
|
|
s.run()
|
|
|
- self.assertTrue(s.clockservice.started)
|
|
|
+ self.assertTrue(s.service.started)
|
|
|
|
|
|
s._popen = _Popen()
|
|
|
s.stop()
|
|
|
- self.assertTrue(s.clockservice.stopped)
|
|
|
+ self.assertTrue(s.service.stopped)
|
|
|
self.assertTrue(s._popen.terminated)
|
|
|
|
|
|
def test_start_stop_threaded(self):
|
|
|
- s = beat.EmbeddedClockService(thread=True)
|
|
|
+ s = beat.EmbeddedService(thread=True)
|
|
|
from threading import Thread
|
|
|
self.assertIsInstance(s, Thread)
|
|
|
- self.assertIsInstance(s.clockservice, beat.ClockService)
|
|
|
- s.clockservice = MockClockService()
|
|
|
+ self.assertIsInstance(s.service, beat.Service)
|
|
|
+ s.service = MockService()
|
|
|
|
|
|
s.run()
|
|
|
- self.assertTrue(s.clockservice.started)
|
|
|
+ self.assertTrue(s.service.started)
|
|
|
|
|
|
s.stop()
|
|
|
- self.assertTrue(s.clockservice.stopped)
|
|
|
+ self.assertTrue(s.service.stopped)
|