Sam,
  I think transactions will work for what you are trying to accomplish. 
Basically, if the record you are trying to modify gets modified while your 
transaction is running your transaction fails and will be retried. Take a look 
at the use cases for transactions. 
  
http://code.google.com/appengine/docs/python/datastore/transactions.html#Uses_For_Transactions

I suggested defining the partner as the parent due to limitations of how 
transactions work. You can only operate on one entity group within a 
transaction. That includes querying.

Robert


On Jul 14, 2010, at 16:54, Sam <couponsys...@gmail.com> wrote:

> Robert,
> 
> Had originally looked at performing it in a transaction and wasn't
> sure whether it isolated the just the transactional portion or the
> data it was working with as well (I couldn't find any clear indication
> of this).  Performing it in a transaction does make it a bit cleaner
> (especially if used multiple times), but this query only needs to be
> executed once per user visit, so I believe all that it would do is
> move the timing issue from the main program logic to a defined
> transaction and we would still have the potential gap in time between
> when the initial query was executed to fetch the data and the put()
> was execute to write it back.
> 
> The problem keeps coming around to the gap between requesting the data
> and updating the data and how to either lock or tag the retrieved
> record so no one else can request it (basically what the SQL Update
> does in a single statement) or to isolate the transaction so only one
> can be processed at a time (not a good solution at all, could
> potentially cause lots of system degradation).
> 
> I guess my main question would be is what role does the transaction
> play - code or data isolation or both?
> 
> By the way, wouldn't have to make the Partner as a parent, the
> PartnerID is known and stored on the CCode table, so effectively:
> 
> def txn():
>    ccode = CCode.all().filter('Assinged', 0)\
>                    .filter('ExpireDate >=', dtCompareDate)\
>                    .filter("PartnerID", intPartnerID).get()
>    if not ccode:
>       # handle no ccode....
>    ccode.SessionID = strSessionID
>    ccode.Assigned = 1
>  db.run_in_transaction(txn)
> 
> should work.
> 
> 
> 
> On Jul 14, 3:52 pm, Robert Kluin <robert.kl...@gmail.com> wrote:
>> Hi Sam,
>>   Is there any way you could slightly refactor the query so that it
>> can be run in a transaction?  Transactions can only operate on one
>> entity group at a time; so, perhaps you can set the a partner as the
>> parent of CCode.
>> 
>>   So your query (in Python) could look more like:
>> 
>>   def txn():
>>     partner_key = db.Key.from_path('Partner', intPartnerID)
>>     ccode = CCode.all().filter('Assinged', 0)\
>>                     .filter('ExpireDate >=', dtCompareDate)\
>>                     .ancestor(partner_key).get()
>>     if not ccode:
>>        # handle no ccode....
>>     ccode.SessionID = strSessionID
>>     ccode.Assigned = 1
>>   db.run_in_transaction(txn)
>> 
>> 
>> 
>> On Wed, Jul 14, 2010 at 11:17 AM, Sam <couponsys...@gmail.com> wrote:
>>> In working with the data store, I've been able to solve all of my
>>> "issues" (coming from a RDBMS background, had to rethink a few
>>> things!), save for one.  In the application I'm working on, it's
>>> necessary to "reserve" a record at a moment in time and then display
>>> that record to the end user, ensuring that each user gets a single
>>> record and no duplicates are issued.  Working with the record prior,
>>> and using SQL as an engine, I was able to use the following query:
>> 
>>> UPDATE CCode SET SessionID = '" + strSessionID + "', Assigned = 1
>>> WHERE Assigned = 0 AND PartnerID = " + str(intPartnerID) + " AND
>>> ExpireDate >= '" + str(dtCompareDate) + "' Limit 1"
>> 
>>> This would update the record in one pass and effectively reserve the
>>> record for the established session, with no time lost inbetween
>>> issuing the update and recording the change while SQL handled any
>>> conflict resolution should two people request a record at the same
>>> time.
>> 
>>> However, dealing with datastore, I seem to be running into some
>>> problems with timing and wanted to know if anyone had any creative
>>> ways around it.
>> 
>>> I realize that I can run a standard GqlQuery to return the results I
>>> need and then update based on the returned result and add the session
>>> to the record without a problem.  What concerns me is the timing
>>> factor.  During the time it takes for the query to execute and the
>>> resulting put() statement, it would be possible for another user to
>>> arrive and make the same basic query recalling the same record set.  I
>>> know I could check for updates against the datastore before writing
>>> back (used to do this years ago...), but this could potentially cause
>>> a deadlock condition when the load on the system became greater and
>>> multiple simultaneous users needed access to the records for selection
>>> and updating.
>> 
>>> Any thoughts on how to work around this?
>> 
>>> --
>>> You received this message because you are subscribed to the Google Groups 
>>> "Google App Engine" group.
>>> To post to this group, send email to google-appeng...@googlegroups.com.
>>> To unsubscribe from this group, send email to 
>>> google-appengine+unsubscr...@googlegroups.com.
>>> For more options, visit this group 
>>> athttp://groups.google.com/group/google-appengine?hl=en.- Hide quoted text -
>> 
>> - Show quoted text -
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Google App Engine" group.
> To post to this group, send email to google-appeng...@googlegroups.com.
> To unsubscribe from this group, send email to 
> google-appengine+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/google-appengine?hl=en.
> 

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine" group.
To post to this group, send email to google-appeng...@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en.

Reply via email to