2012-04-17 36 views
37

Nếu tôi có một chức năng được xác định như sau:Làm thế nào để tự động thêm/xóa nhiệm vụ tuần hoàn để cần tây (celerybeat)

def add(x,y): 
    return x+y 

Có cách nào để tự động thêm chức năng này như một PeriodicTask cần tây và kick nó ra tại thời gian chạy? Tôi muốn để có thể làm điều gì đó tương tự (giả):

some_unique_task_id = celery.beat.schedule_task(add, run_every=crontab(minute="*/30")) 
celery.beat.start(some_unique_task_id) 

Tôi cũng muốn dừng hoặc loại bỏ nhiệm vụ tự động với một cái gì đó tương tự (giả):

celery.beat.remove_task(some_unique_task_id) 

hoặc

celery.beat.stop(some_unique_task_id) 

FYI Tôi không sử dụng thiết bị djcelery, cho phép bạn quản lý các tác vụ định kỳ thông qua quản trị viên django.

Trả lời

18

Không, tôi xin lỗi, điều này là không thể đối với tình trạng cần thiết thường xuyên.

Nhưng có thể dễ dàng mở rộng để thực hiện những gì bạn muốn, ví dụ: bộ lập lịch django-celery chỉ là một phân lớp đọc và ghi lịch biểu vào cơ sở dữ liệu (với một số tối ưu hóa ở trên cùng).

Ngoài ra, bạn có thể sử dụng bộ lập lịch django-cần tây ngay cả đối với các dự án không phải Django.

Something như thế này:

  • Install django + django-cần tây:

    $ pips cài đặt -U django django-cần tây

  • Thêm các thiết lập sau đây để celeryconfig của bạn:

    DATABASES = { 
        'default': { 
         'NAME': 'celerybeat.db', 
         'ENGINE': 'django.db.backends.sqlite3', 
        }, 
    } 
    INSTALLED_APPS = ('djcelery',) 
    
  • Tạo bảng cơ sở dữ liệu :

    $ PYTHONPATH=. django-admin.py syncdb --settings=celeryconfig 
    
  • Bắt đầu celerybeat với lịch trình cơ sở dữ liệu:

    $ PYTHONPATH=. django-admin.py celerybeat --settings=celeryconfig \ 
        -S djcelery.schedulers.DatabaseScheduler 
    

Cũng có những djcelerymon lệnh mà có thể được sử dụng cho phi Django dự án để bắt đầu celerycam và một máy chủ web Django Admin cùng một quá trình, bạn có thể sử dụng điều đó để cũng chỉnh sửa các tác vụ định kỳ của mình trong giao diện web đẹp mắt:

$ djcelerymon 

(Lưu ý đối với một số lý do djcelerymon không thể ngừng sử dụng tổ hợp phím Ctrl + C, bạn phải sử dụng tổ hợp phím Ctrl + Z + giết% 1)

+1

Bạn có thể đề cập đến mã để thêm công việc và xóa không? Xin lỗi tôi không nhận được. –

+6

Bất kỳ thay đổi nào trong giai đoạn này từ 2012 đến 2016? – Tanay

32

Câu hỏi này được trả lời trên google groups.

TÔI KHÔNG TÁC GIẢ, tất cả các tín dụng đi vào Jean Đánh dấu

Dưới đây là một giải pháp thích hợp cho việc này.Xác nhận làm việc, Trong kịch bản của tôi, Tôi phân loại nhiệm vụ định kỳ và tạo ra một mô hình trong số đó vì tôi có thể thêm các trường khác vào mô hình như tôi cần và cũng có thể để thêm phương thức "chấm dứt" . Bạn phải đặt thuộc tính được kích hoạt theo định kỳ cho thuộc tính thành False và lưu nó trước khi xóa. Toàn bộ phân lớp không phải là phải, phương thức schedule_every là phương thức thực sự thực hiện công việc. Khi bạn đã sẵn sàng chấm dứt công việc (nếu bạn không phân loại nó), bạn chỉ có thể sử dụng PeriodicTask.objects.filter (name = ...) để tìm kiếm tác vụ của mình, tắt rồi xóa.

Hy vọng điều này sẽ hữu ích!

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() 
+1

Đây phải là câu trả lời được chấp nhận. – kai

+1

@kai 'IntervalSchedule',' PeriodicTask', vv, là các lớp 'djcelery' và OP cho biết anh ấy không sử dụng' djcelery'. Chắc chắn hữu ích. – Chris

2

Bạn có thể kiểm tra flask-djcelery này mà cấu hình bình và djcelery và cũng cung cấp browseable còn lại api

2

Có một thư viện gọi django-cần tây-beat mà cung cấp các mô hình một nhu cầu. Để làm cho nó tự động tải các tác vụ định kỳ mới, người ta phải tạo Trình lập lịch biểu riêng của mình.

from django_celery_beat.schedulers import DatabaseScheduler 


class AutoUpdateScheduler(DatabaseScheduler): 

    def tick(self, *args, **kwargs): 
     if self.schedule_changed(): 
      print('resetting heap') 
      self.sync() 
      self._heap = None 
      new_schedule = self.all_as_schedule() 

      if new_schedule: 
       to_add = new_schedule.keys() - self.schedule.keys() 
       to_remove = self.schedule.keys() - new_schedule.keys() 
       for key in to_add: 
        self.schedule[key] = new_schedule[key] 
       for key in to_remove: 
        del self.schedule[key] 

     super(AutoUpdateScheduler, self).tick(*args, **kwargs) 

    @property 
    def schedule(self): 
     if not self._initial_read and not self._schedule: 
      self._initial_read = True 
      self._schedule = self.all_as_schedule() 

     return self._schedule 
+0

Cảm ơn. Đã không làm việc ngay lập tức nhưng sử dụng 'to_add = [phím cho khóa trong new_schedule.keys() nếu khóa không có trong self.schedule.keys()]' và tương tự cho 'to_remove' đã làm thủ thuật. Tại sao đây không phải là một lựa chọn tiêu chuẩn? Cho đến bây giờ, tôi đã phải có nhiệm vụ Celery gọi các nhiệm vụ Celery khác với đếm ngược. Điều đó nghe không tốt với tôi. – freethebees

Các vấn đề liên quan