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.

Reply via email to