使用芹菜

时间:2016-06-19 16:35:57

标签: python django celery celery-task

我需要以随机的时间间隔运行“CreateNotifications”任务。 以下是我在CELERY设置中尝试做的事情。

t = random.randint(45, 85)
## print "time = ", t

## celery app configuration
app.conf.CELERYBEAT_SCHEDULE = {
    # Executes at every 't' interval, where t is random
    'create-notifications': {
        'task': 'apps.notifications.tasks.CreateNotifications',
        'schedule': timedelta(seconds=t),
    },
}

现在问题是CELERY的这些设置只执行一次(当我运行命令python manage.py runserver时),因此变量't'因此timedelta中'seconds'的值得到一个随机值,但只有一次。

最终使上述过程成为一个固定周期为X秒的周期过程,当我启动服务器时,只会随机选择X.

或者我尝试运行单个任务并在其中使用无限循环,并且随机延迟,以便芹菜只自动检测一个任务,该任务永远不会结束。我的目的是通过while循环中的随机延迟来解决的。 像这样(注意 - >'while'在函数CreateNotifications()中)

@app.task
def CreateNotifications():

while True:

    upper_limit = models.MyUser.objects.all().aggregate(Max('id'))
    lower_limit = models.MyUser.objects.all().aggregate(Min('id'))

    ## select a user to be notified randomly

    to_user = None
    to = 0

    while to_user is None:
        to = random.randint(lower_limit['id__min'], upper_limit['id__max'])
        try:
            to_user = models.MyUser.objects.get(id=to)
        except:
            pass

    ## select a user to be notified from randomly

    frm_user = None
    frm = to

    while frm_user is None:
        while frm == to:
            frm = random.randint(lower_limit['id__min'], upper_limit['id__max'])
        try:
            frm_user = models.MyUser.objects.get(id=frm)
        except:
            pass

    notif_type = ['comment on', 'liked', 'shared']
    notif_media = ['post', 'picture', 'video']

    models.Notification.objects.create(
        notified_user = to_user,
        notifier = frm_user,
        notification_type = random.choice(notif_type),
        notification_media = random.choice(notif_media))

    to_user.new_notification_count += 1
    to_user.save()


    t = random.randint(35, 55)
    print "delay = ", t
    time.sleep(t)

它完全按照我的意愿行事,但现在有4个不同的工作人员执行相同的任务,但我只想要一个。

我已尝试更改位于我的virtualenv / bin /目录中的celeryd文件,如此处所示 - > Celery. Decrease number of processes

因为/ etc / defaults /中没有celeryd文件但仍然没有成功

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

你真的不应该在Celery任务中加入无限循环。如果你需要一个专门的过程,最好是自己运行它而不是通过Celery。

您可以在任务运行时重新安排新任务。如下所示:

@app.task
def create_notifications():
     try:
          #
     finally:
          t = random.randint(45, 85)
          create_notifications.apply_async(countdown=t)

另一种选择是让调度程序任务按常规计划运行,但在不久的将来将通知任务排队一段随机时间。例如,如果调度程序任务每45秒运行一次。

@app.task
def schedule_notifications():
     t = random.randint(0, 40)
     create_notifications.apply_async(countdown=t)