On 6 sep, 15:45, Andy <selforgani...@gmail.com> wrote: > I have a model MyModel that has a field expiration_datetime. > > Every time a user retrieves an instance of MyModel I need to first > check if it has expired or not. If it has expired, than I need to > increment some counter, update others, and then reset the > expiration_datetime to some time in the future. > > So the view would do something like: > > if object.expiration_datetime < datetime.datetime.now(): > object.counter = F('counter') + 1 > object.expiration_datetime = F('expiration_datetime') + > datetime.timedelta(days=1) > object.save() > > There's a race condition in the code above. Say thread 1 checks and > finds that the current instance has expired, it proceeds to increment > the counter and reset the expiration datetime. But before it could do > so, thread 2 is scheduled and does the same. By the time thread 1 > finally finishes, counter has been incremented twice and > expration_datetime has been reset twice. > > This looks like a pretty common issue. How do I handle it?
The SQL "update" statement is atomic (well, it's supposed to be at least), so queryset.update should solve the problem (nb : not tested): YourModel.objects.filter( pk=object.pk, expiration_datetime < datetime.datetime.now() ).update( counter== F('counter') + 1, expiration_datetime = F('expiration_datetime') + datetime.timedelta(days=1) ) HTH -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.