Bulk.update()之后Django循环遍历对象



此代码在cron上运行。因此,我想立即更新对象的状态,这样,如果第二个cron在当前cron完成之前启动,这些对象就不会再次被拾取(这最终会在我的应用程序中发生(

# Grab all pending emails.
emails = delivery_que.objects.filter(status='PENDING')
emails.update(status='SENDING')
# Loop through the pending emails.
for email in emails:

当前的代码不起作用,因为在I.update((之后,我似乎不再能够访问这些对象。

这是我实现的变通方法:

# Grab all pending emails.
emails = delivery_que.objects.filter(status='PENDING')
emails.update(status='SENDING')
emails = delivery_que.objects.filter(status='SENDING')
# Loop through the pending emails.
for email in emails:

我还缺少其他更好的解决方案吗?我不想再查询数据库,而是从第一次查询中重新选择我应该已经可以访问的对象。

这里的问题是,您正在运行重叠的进程,并且在任何时间点都不知道对方在做什么。

简单的解决方案:

  1. 当作业启动时,请检查锁定记录。如果存在,请退出作业
  2. 添加一个锁定记录(到DB中的模型,触摸一个文件,等等(
  3. 处理作业
  4. 将锁定记录作为作业的最后一件事删除

稍微复杂一点的解决方案:

  1. 在作业开始时,将PENDING中的所有记录更新为该进程的唯一值(例如PROCESSING_<uuid>(
  2. 对具有该唯一值的记录运行更新

您也可以通过向模型中添加另一个字段来实现这一点,例如processing_id,并检查该字段是否为空以及是否具有正确的PENDING状态。

可能是最复杂的解决方案:

  • 使过程幂等

我的意思是,它在同一条记录上运行两次并不重要。从你上面发布的代码来看,这实际上是真的,因为你所做的只是将状态更改为SENDING,但我想有些代码你没有显示,用户会收到双重电子邮件。

如果你有代码来确保不会发送双重邮件,这就不是问题——对象可能会被处理两次,但它只会在第一次发送电子邮件。

在理想的世界里,所有像这样的过程都应该是幂等的,只是为了确保你永远不会遇到任何问题,如果有人在不应该的时候设法运行它。

最新更新