我试图找到一种能够从django管理员打开/关闭芹菜任务的方法。这主要是为了在这些服务停机或具有计划的维护期时禁用调用外部服务的任务。
对于我的周期性任务,这很容易,特别是对于django-celery。但对于按需调用的任务,我遇到了一些麻烦。目前我正在探索只在TaskControl模型中存储各种任务的开/关状态,然后在任务执行开始时检查该状态,如果状态为False则返回None。这使得每次任务开始时由于所有额外的数据库查找而感到肮脏。我可以使用不是db的缓存后端,但是为这些少数键/值对添加缓存似乎有点过分。
在models.py
中# this is a singleton model. singleton code bits omitted for brevity.
class TaskControl(models.Model):
some_status = models.BooleanField(default=True)
# more statuses
在tasks.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
有什么更好的方法可以做到这一点?
答案 0 :(得分:2)
选项1.尝试简单的方法。看它是否会影响性能。如果没有,就会失去“肮脏”的感觉。
选项2.使用单例缓存进程内存。向您的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的remote control强制所有工作人员重新加载TaskControl
(您必须编写自己的控制命令,并且我不知道你需要的所有内部是否是公共API。
选项4,仅适用于所有Celery工作人员在一台计算机上运行的情况。将on / off标志存储为该计算机文件系统上的文件。使用os.path.exists
查询其存在(应该是单个stat()
或其他东西,足够便宜)。如果工作人员和管理员面板位于不同的计算机上,请使用特殊的Celery任务来创建/删除文件。
选项5.与选项4类似,但在管理员/网络机器上:如果文件存在,则不要首先排队任务。