我想确保给定的通知只发送一次,即使任务的两个实例同时运行(任务在Celery中运行并且可能会自动重启)。这就是我在做的事情:
with transaction.atomic():
update_count = (Notification.objects
.filter(id=notification.id, was_sent=None)
.update(was_sent=timezone.now()))
if update_count == 1:
self.send_message(notification)
这个想法是,只有当UPDATE
事先为空时才会在SQL级别上成为was_sent
命令,并且这是原子的,所以如果另一个进程试图在同一时刻,一个会成功(update_count==1
)而另一个会失败(update_count==0
)。
transaction.atomic()
中的换行是为了在邮件失败时回滚更新。我不认为它会影响UPDATE
本身的原子性。
尽管如此,我发现send_message
功能的影响在一小部分案例中重复。我错误地认为其他进程会立即“看到”更新吗?
Django 1.6,PostgreSQL 9.2.6