由芹菜工人运行的任务,主管获取datetime.date.today()的错误值

问题描述 投票:0回答:1

我有一个任务,使用芹菜节拍定期运行。芹菜殴打和芹菜工人(在单独的队列中)都使用主管运行。

任务是使用python的datetime.date.today()函数存储运行日期。问题是datetime.date.today()在工作人员重新启动时返回正确的日期,但是在使用芹菜节拍调用相同任务的后几天,datetime.date.today()函数返回工作人员重新启动而不是当前日期的相同日期。

任务在utc时区运行,我交叉检查执行日期。当我尝试使用celery beat传递运行日期为args时也是如此(在这种情况下,它返回芹菜节拍的开始/重启日期而不是当前日期)。我仍然无法弄清楚为什么会这样。服务器系统日期/时间似乎正常。

这是celery beat和celery worker队列的supervisor配置(这不是整个配置,只是相关的块)

[supervisord]
logfile=/dir/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB        ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10           ; (num of main logfile rotation backups;default 10)
loglevel=info                ; (log level;default info; others: debug,warn,trac
pidfile=supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false               ; (start in foreground if true;default false)
minfds=1024                  ; (min. avail startup file descriptors;default 1024
minprocs=200                 ; (min. avail process descriptors;default 200)


[program:celery_worker_custom_queue]
environment =
    LC_ALL=en_US.UTF-8,
    LANG=en_US.UTF-8

command = /usr/local/bin/celery  --concurrency=5  -A config worker -l info -Q custom_queue -n workername@%%h
directory = /path/to/dir
priority = 2
user = user
numprocs = numprocs
stderr_logfile = log_file_path
stdout_logfile = log_file_path
autostart = true
autorestart = true


[program:celery_beat]
environment =
    LC_ALL=en_US.UTF-8,
    LANG=en_US.UTF-8

command = /usr/local/bin/celery -A config beat -l info
directory = /path/to/dir
priority = 3
user = user
numprocs = numprocs
stderr_logfile = log_file_path
stdout_logfile = log_file_path
autostart = true
autorestart = true

我检查时在网上找不到任何类似的问题。此外,我不能删除主管。

在配置中我能做些什么吗?另外,我第一次使用这样的设置,我是否在概念上遗漏了什么?请帮忙

编辑:我已经在我的本地机器上测试了它,它在没有主管的情况下正常运行。任务代码如下(删除不使用运行日期的代码)

 import datetime as dt

 run_date = (dt.date.today()).strftime('%Y-%m-%d')

 @celeryApp.task(bind=True, name="api_task",queue="custom_queue")
 def api_task(self, start_date=run_date):
   api_run_date = start_date
   #api calls and object calculations; api_run_date is not used anywhere..
   task_status(obj=status_obj, status=True, run_date=api_run_date)

 def task_status(obj, status=False, run_date=run_date):
    is_done = status
    # print(obj,' - ',run_date,' - ',is_done)
    done, created = ModelName.objects.update_or_create(date=run_date, defaults={'is_done': is_done}, obj_inst=obj)
    done.save()
django python-3.x celery supervisord celerybeat
1个回答
1
投票

我认为问题在于你使用日期的方式。将datetime.date.today()值存储在run_date全局变量中,然后将其用作任务的start_date参数的默认值。但是,当在Python中定义函数时,默认参数值仅计算一次。因此,除非您在调用start_date时实际为api_task提供值,否则您始终使用相同的值。该值是run_date全局变量的值,而该变量在首次导入模块时仅被评估一次。

处理这个问题的正确方法是这样的:

def api_task(self, start_date=None):
   # use `start_date` if given or current date
   api_run_date = start_date or dt.date.today().strftime('%Y-%m-%d')
   #api calls and object calculations; api_run_date is not used anywhere..
   task_status(obj=status_obj, status=True, run_date=api_run_date)
© www.soinside.com 2019 - 2024. All rights reserved.