Re: update with where clause constraints?

2010-02-06 Thread Karen Tracey
On Sat, Feb 6, 2010 at 8:55 AM, Malcolm Box  wrote:

> 2010/2/5 Jared Smith 
>
>> My use case is that I'll have multiple users trying to update a set of
>> objects and I want to make sure that any user committing a change has
>> knowledge of the existing state.  I was going to model that with a version
>> number so an update would look like:
>>
>
> Maybe I'm missing something, but this sounds like the canonical use of
> ETags.  Provide an Etag with the read, then when the update comes in check
> if the ETag matches what is calculated for the current state of the DB.
>
> If it does, let the update through.  If not, then force the user to retry
> based on the new state.
>

Note anything done like this in Django app code is liable to run into
multi-thread/multi-process race conditions. A typical production deployment
environment will have multiple threads and/or processes handling requests
simultaneously. Thus current state of the DB when a request is received is
not necessarily going to be the same as current state of the DB by the time
the request processing thread gets around to actually making the update --
one request processing thread could have already passed the point of
accepting an update but not quite gotten around to making the change in the
DB when a 2nd request processing thread decides it's also OK to accept an
update. Last one to actually issue the update wins, the other thread's
update is lost.

Using an atomic SQL UPDATE with a WHERE clause specifying the version
requirement, which is what QuerySet update() allows, pushes the
responsibility for dealing with this race condition onto the DB. The DB will
ensure that only one of the threads gets to make the update, and the Django
app code can know which it is based on the result of the update() call.

Karen

-- 
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.



Re: update with where clause constraints?

2010-02-06 Thread Malcolm Box
2010/2/5 Jared Smith 

> My use case is that I'll have multiple users trying to update a set of
> objects and I want to make sure that any user committing a change has
> knowledge of the existing state.  I was going to model that with a version
> number so an update would look like:
>

Maybe I'm missing something, but this sounds like the canonical use of
ETags.  Provide an Etag with the read, then when the update comes in check
if the ETag matches what is calculated for the current state of the DB.

If it does, let the update through.  If not, then force the user to retry
based on the new state.

Cheers,

Malcolm

-- 
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.



Re: update with where clause constraints?

2010-02-04 Thread Karen Tracey
On Thu, Feb 4, 2010 at 8:08 PM, Jared Smith  wrote:

> My use case is that I'll have multiple users trying to update a set of
> objects and I want to make sure that any user committing a change has
> knowledge of the existing state.  I was going to model that with a version
> number so an update would look like:
>
> update table set col=foo, col1=bar where id=pknum &&
> version_number=
>
> Desired result are the following::
>
> --If a user has the correct previous version the update goes through
> --if they don't have the correct previous version it should do nothing
> (I'll throw an exception or return something to the upper layer to indicate
> the fact that the user needs to try again from the latest version...)
>
> My question is how can I do an update like the above in Django?
>

http://docs.djangoproject.com/en/dev/topics/db/queries/#updating-multiple-objects-at-once

Though it sounds like you do not want to update multiple at once, you can
use the same call and know based on its returned value (it returns how many
rows it updated) whether it worked or not. If one is returned, you know the
version read was unchanged for the update and all is fine.  If zero is
returned then apparently someone else changed the row in the meantime. (You
probably also want to include an increment of the version_number field as an
F expression in the update call.)

Karen

-- 
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.



update with where clause constraints?

2010-02-04 Thread Jared Smith
My use case is that I'll have multiple users trying to update a set of
objects and I want to make sure that any user committing a change has
knowledge of the existing state.  I was going to model that with a version
number so an update would look like:

update table set col=foo, col1=bar where id=pknum && version_number=

Desired result are the following::

--If a user has the correct previous version the update goes through
--if they don't have the correct previous version it should do nothing (I'll
throw an exception or return something to the upper layer to indicate the
fact that the user needs to try again from the latest version...)

My question is how can I do an update like the above in Django?  It looks
like the save API hides the fact whether it is insert or update; however I
can easily determine this myself (haven't found a way that I can add
additional criteria on the update).  I saw the following patch:

http://code.djangoproject.com/ticket/2705

And that could maybe meet my needs but I'm wondering if there is any
existing way to accomplish this without having to patch Django? (hoping I'm
missing some existing way to accomplish this)

Please let me know if you have any suggestions.

Thanks,

Jared

-- 
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.