我正试图找到一种方法,可以从django管理员打开/关闭芹菜任务。这主要是为了在外部服务关闭或有计划维护期时禁用调用这些服务的任务。
对于我的周期性任务来说,这很容易,尤其是使用django芹菜。但对于按需调用的任务,我遇到了一些麻烦。目前,我正在探索在TaskControl模型中存储各种任务的打开/关闭状态,然后在任务执行开始时检查该状态,如果状态为False,则返回None。由于每次任务启动时都要进行额外的数据库查找,这让我感觉很糟糕。我可以使用不是数据库的缓存后端,但只为这几对键/值添加缓存似乎有点过头了。
在模型中.py
# this is a singleton model. singleton code bits omitted for brevity.
class TaskControl(models.Model):
some_status = models.BooleanField(default=True)
# more statuses
在任务中.py
@celery.task(ignore_result=True)
def some_task():
task_control = TaskControl.objects.get(pk=1)
if not task_control.some_status:
return None
# otherwise execute task as normal
有什么更好的方法可以做到这一点?
选项1。试试你的简单方法。看看它是否会影响性能。如果没有,就失去"肮脏"的感觉。
选项2。使用singleton在进程内存中缓存。为TaskControl
型号添加新鲜度信息:
class TaskControl(models.Model):
some_status = models.BooleanField(default=True)
# more statuses
expires = models.DateTimeField()
check_interval = models.IntegerField(default=5 * 60)
def is_stale(self):
return (
(datetime.utcnow() >= self.expires) or
((datetime.utcnow() - self.retrieved).total_seconds >= self.check_interval))
然后在task_ctl.py
:中
_control = None
def is_enabled():
global _control
if (_control is None) or _control.is_stale():
_control = TaskControl.objects.get(pk=1)
# There's probably a better way to set `retrieved`,
# maybe with a signal or a `Model` override,
# but this should work.
_control.retrieved = datetime.utcnow()
return _control.some_status
选项3。与选项2类似,但不要使用基于时间的过期,而是使用Celery的远程控制来强制所有工作程序重新加载TaskControl
(您必须编写自己的控制命令,我不知道您需要的所有内部是否都是公共API)。
选项4,仅适用于所有Celery员工在一台机器上运行的情况。将打开/关闭标志作为文件存储在该机器的文件系统中。用os.path.exists
(应该是单个stat()
之类的,足够便宜)来查询它的存在。如果工人和管理面板在不同的机器上,请使用特殊的Celery任务来创建/删除文件。
选项5。类似于选项4,但在admin/web机器上:如果文件存在,首先不要将任务排队。