mga*_*lgs 5 python django locking celery database-locking
我有一个Django应用程序,将对象保存到数据库中,还有一个芹菜任务,该任务定期对其中一些对象进行一些处理。问题在于,在芹菜任务已选择要处理的对象之后,但芹菜任务实际完成处理并保存之前,用户可以删除对象。因此,当celery任务确实调用时.save(),即使用户删除了该对象,该对象也会重新出现在数据库中。当然,这对于用户来说确实很诡异。
所以这是一些显示问题的代码:
def my_delete_view(request, pk):
thing = Thing.objects.get(pk=pk)
thing.delete()
return HttpResponseRedirect('yay')
@app.task
def my_periodic_task():
things = get_things_for_processing()
# if the delete happens anywhere between here and the .save(), we're hosed
for thing in things:
process_thing(thing) # could take a LONG time
thing.save()
Run Code Online (Sandbox Code Playgroud)
我考虑过尝试通过添加原子块和事务来修复它,然后在保存对象之前测试该对象是否确实存在,以进行修复:
@app.task
def my_periodic_task():
things = Thing.objects.filter(...some criteria...)
for thing in things:
process_thing(thing) # could take a LONG time
try:
with transaction.atomic():
# just see if it still exists:
unused = Thing.objects.select_for_update().get(pk=thing.pk)
# no exception means it exists. go ahead and save the
# processed version that has all of our updates.
thing.save()
except Thing.DoesNotExist:
logger.warning("Processed thing vanished")
Run Code Online (Sandbox Code Playgroud)
这是做这种事情的正确模式吗?我的意思是,我将在生产中运行它几天之内找出它是否可以工作,但是很高兴知道是否还有其他公认的模式可以完成这种事情。
我真正想要的是能够更新数据库中仍然存在的对象。我可以接受用户编辑与进行的编辑之间的竞争process_thing,而且我总是可以在refresh_from_db之前加入,process_thing以最大程度地减少丢失用户编辑的时间。但是我绝对不能在用户删除对象后使它们重新出现。
目前看来,“再次原子选择,然后保存”的模式就足够了:
@app.task
def my_periodic_task():
things = Thing.objects.filter(...some criteria...)
for thing in things:
process_thing(thing) # could take a LONG time
try:
with transaction.atomic():
# just see if it still exists:
unused = Thing.objects.select_for_update().get(pk=thing.pk)
# no exception means it exists. go ahead and save the
# processed version that has all of our updates.
thing.save()
except Thing.DoesNotExist:
logger.warning("Processed thing vanished")
Run Code Online (Sandbox Code Playgroud)
(这与我原来的问题中的代码相同)。