Replacing Celerybeat with Chronos

2019-04-05 18:30发布

问题:

How mature is Chronos? Is it a viable alternative to scheduler like celery-beat?

Right now our scheduling implements a periodic "heartbeat" task that checks of "outstanding" events and fires them if they are overdue. We are using python-dateutil's rrule for defining this.

We are looking at alternatives to this approach, and Chronos seems a very attactive alternative: 1) it would mitigate the necessity to use a heartbeat schedule task, 2) it supports RESTful submission of events with ISO8601 format, 3) has a useful interface for management, and 4) it scales.

The crucial requirement is that scheduling needs to be configurable on the fly from the Web Interface. This is why can't use celerybeat's built-in scheduling out of the box.


Are we going to shoot ourselves in the foot by switching over to Chronos?

回答1:

This SO has solutions to your dynamic periodic task problem. It's not the accepted answer at the moment:

 from djcelery.models import PeriodicTask, IntervalSchedule
 from datetime import datetime

 class TaskScheduler(models.Model):

     periodic_task = models.ForeignKey(PeriodicTask)

     @staticmethod
     def schedule_every(task_name, period, every, args=None, kwargs=None):
     """ schedules a task by name every "every" "period". So an example call would be:
          TaskScheduler('mycustomtask', 'seconds', 30, [1,2,3]) 
          that would schedule your custom task to run every 30 seconds with the arguments 1 ,2 and 3 passed to the actual task. 
     """
         permissible_periods = ['days', 'hours', 'minutes', 'seconds']
         if period not in permissible_periods:
             raise Exception('Invalid period specified')
         # create the periodic task and the interval
         ptask_name = "%s_%s" % (task_name, datetime.datetime.now()) # create some name for the period task
         interval_schedules = IntervalSchedule.objects.filter(period=period, every=every)
         if interval_schedules: # just check if interval schedules exist like that already and reuse em
             interval_schedule = interval_schedules[0]
         else: # create a brand new interval schedule
             interval_schedule = IntervalSchedule()
             interval_schedule.every = every # should check to make sure this is a positive int
             interval_schedule.period = period 
             interval_schedule.save()
         ptask = PeriodicTask(name=ptask_name, task=task_name, interval=interval_schedule)
         if args:
             ptask.args = args
         if kwargs:
             ptask.kwargs = kwargs
         ptask.save()
         return TaskScheduler.objects.create(periodic_task=ptask)

     def stop(self):
         """pauses the task"""
         ptask = self.periodic_task
         ptask.enabled = False
         ptask.save()

     def start(self):
         """starts the task"""
         ptask = self.periodic_task
         ptask.enabled = True
         ptask.save()

     def terminate(self):
         self.stop()
         ptask = self.periodic_task
         self.delete()
         ptask.delete()

I haven't used djcelery yet, but it supposedly has an admin interface for dynamic periodic tasks.