[appengine-java] Best practice for multithreaded access/update to entity

2011-04-03 Thread Peter Backx
I have an application that accesses a user entity. This entity also contains 
a number of user specific settings that the user can update. Some of those 
settings are updated by different servlets in parallel (for instance 
uploading a profile picture to the blobstore)

I'm having some serious issues keeping everything in sync. If I'm not 
careful, I can easily overwrite updates that have been done in another 
thread.

I have the feeling this is a recurring issue for many GAE application, so 
I'm looking for some best practices of how to deal with it.

In the relational world, often a "version" column is added. Before updating 
a row, the version number in the database is compared to the one in memory. 
I suppose I can implement something like that on GAE too, but I was 
wondering whether there are better/other options available in the NoSQL 
world.


Regards,
Peter

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



Re: [appengine-java] Best practice for multithreaded access/update to entity

2011-04-04 Thread Ikai Lan (Google)
If the updates are that important, just use a transaction since it
effectively does what Didier describes.

Ikai Lan
Developer Programs Engineer, Google App Engine
Blog: http://googleappengine.blogspot.com
Twitter: http://twitter.com/app_engine
Reddit: http://www.reddit.com/r/appengine



On Sun, Apr 3, 2011 at 5:10 AM, Peter Backx  wrote:

> I have an application that accesses a user entity. This entity also
> contains a number of user specific settings that the user can update. Some
> of those settings are updated by different servlets in parallel (for
> instance uploading a profile picture to the blobstore)
>
> I'm having some serious issues keeping everything in sync. If I'm not
> careful, I can easily overwrite updates that have been done in another
> thread.
>
> I have the feeling this is a recurring issue for many GAE application, so
> I'm looking for some best practices of how to deal with it.
>
> In the relational world, often a "version" column is added. Before updating
> a row, the version number in the database is compared to the one in memory.
> I suppose I can implement something like that on GAE too, but I was
> wondering whether there are better/other options available in the NoSQL
> world.
>
>
> Regards,
> Peter
>
> --
> You received this message because you are subscribed to the Google Groups
> "Google App Engine for Java" group.
> To post to this group, send email to
> google-appengine-java@googlegroups.com.
> To unsubscribe from this group, send email to
> google-appengine-java+unsubscr...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/google-appengine-java?hl=en.
>

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



Re: [appengine-java] Best practice for multithreaded access/update to entity

2011-04-05 Thread Jeff Schnitzer
When I first started using appengine, my initial impression of
transactions is "what good is this?" because of the entity group
limitation.  But I've since found that single-entity transactions are
really useful for preventing exactly this issue.

So, if you are worried about conflicts, use a transaction.

One thing that helps in javaland is to adapt Python's programming
model of a transaction.  Implement your transactional behavior as an
inner class that you hand off to a method that will retry it as many
times as necessary.

Jeff

On Mon, Apr 4, 2011 at 1:34 AM, Ikai Lan (Google)  wrote:
> If the updates are that important, just use a transaction since it
> effectively does what Didier describes.
> Ikai Lan
> Developer Programs Engineer, Google App Engine
> Blog: http://googleappengine.blogspot.com
> Twitter: http://twitter.com/app_engine
> Reddit: http://www.reddit.com/r/appengine
>
>
> On Sun, Apr 3, 2011 at 5:10 AM, Peter Backx  wrote:
>>
>> I have an application that accesses a user entity. This entity also
>> contains a number of user specific settings that the user can update. Some
>> of those settings are updated by different servlets in parallel (for
>> instance uploading a profile picture to the blobstore)
>>
>> I'm having some serious issues keeping everything in sync. If I'm not
>> careful, I can easily overwrite updates that have been done in another
>> thread.
>>
>> I have the feeling this is a recurring issue for many GAE application, so
>> I'm looking for some best practices of how to deal with it.
>>
>> In the relational world, often a "version" column is added. Before
>> updating a row, the version number in the database is compared to the one in
>> memory. I suppose I can implement something like that on GAE too, but I was
>> wondering whether there are better/other options available in the NoSQL
>> world.
>>
>>
>> Regards,
>> Peter
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Google App Engine for Java" group.
>> To post to this group, send email to
>> google-appengine-java@googlegroups.com.
>> To unsubscribe from this group, send email to
>> google-appengine-java+unsubscr...@googlegroups.com.
>> For more options, visit this group at
>> http://groups.google.com/group/google-appengine-java?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Google App Engine for Java" group.
> To post to this group, send email to google-appengine-java@googlegroups.com.
> To unsubscribe from this group, send email to
> google-appengine-java+unsubscr...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/google-appengine-java?hl=en.
>

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



Re: [appengine-java] Best practice for multithreaded access/update to entity

2011-04-07 Thread Peter Backx
Hi Ikai,

Could you expand your answer a little? Do you mean that I don't need to 
manage a timestap/version if I use transactions? Or do you mean I should use 
transactions to combine a read (to check for a changed timestamp/version) 
with a write?

If I don't manage the timestamp myself, how does AppEngine know another 
process change the data since the last read? part of the key?

Sorry for those beginner questions, I started using the datastore via the 
JDO API with a relational background, but it looks it isn't always the best 
fit for typical datastore issues. Objectify looks much better as it is 
specifically designed for it.


Thanks every one for your answers

Peter

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



Re: [appengine-java] Best practice for multithreaded access/update to entity

2011-04-07 Thread Jeff Schnitzer
This video will help you immensely:

http://sites.google.com/site/io/under-the-covers-of-the-google-app-engine-datastore

You can skip to the end if you just want to grok the transactions, but
the rest of it is extraordinarily helpful as well.

You are correct, if you use transactions, you do not need to manage a
timestamp.  This is because GAE has its own timestamp on each entity
group.  When you load an entity in a transaction, GAE checks this
timestamp.  When you commit, it checks the timestamp again - and if
something changed, you get a ConcurrentModificationException.  By
running your transaction in a retry loop and checking for
ConcurrentModificationException, you can safely ensure that non-stale
data is written.

Note that this isn't too far off from a description of what happens
when you do a non-transactional put().  It's just that the transaction
and retry loop are performed within the datastore itself.  Creating an
explicit transaction just provides the opportunity for your business
logic to get "in the loop" so to speak.

Jeff

On Thu, Apr 7, 2011 at 7:09 AM, Peter Backx  wrote:
> Hi Ikai,
>
> Could you expand your answer a little? Do you mean that I don't need to
> manage a timestap/version if I use transactions? Or do you mean I should use
> transactions to combine a read (to check for a changed timestamp/version)
> with a write?
>
> If I don't manage the timestamp myself, how does AppEngine know another
> process change the data since the last read? part of the key?
>
> Sorry for those beginner questions, I started using the datastore via the
> JDO API with a relational background, but it looks it isn't always the best
> fit for typical datastore issues. Objectify looks much better as it is
> specifically designed for it.
>
>
> Thanks every one for your answers
>
> Peter
>
> --
> You received this message because you are subscribed to the Google Groups
> "Google App Engine for Java" group.
> To post to this group, send email to google-appengine-java@googlegroups.com.
> To unsubscribe from this group, send email to
> google-appengine-java+unsubscr...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/google-appengine-java?hl=en.
>

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



Re: [appengine-java] Best practice for multithreaded access/update to entity

2011-04-07 Thread Jeff Schnitzer
This inspired me to add a little snippet to Objectify's BestPractices document:

http://code.google.com/p/objectify-appengine/wiki/BestPractices#Use_Pythonic_Transactions

Basically, to run an automatically repeated transaction that updates a
(non-sharded to make the example simple) counter, I would do this:

DAOT.repeatInTransaction(new Transactable() {
@Override
public void run(DAOT daot)
{
Counter count = daot.ofy().find(Counter.class, COUNTER_ID);
count.increment();
daot.ofy().put(count);
}
});

This will guarantee that updates to the counter are not lost.

Jeff

On Thu, Apr 7, 2011 at 10:08 AM, Jeff Schnitzer  wrote:
> This video will help you immensely:
>
> http://sites.google.com/site/io/under-the-covers-of-the-google-app-engine-datastore
>
> You can skip to the end if you just want to grok the transactions, but
> the rest of it is extraordinarily helpful as well.
>
> You are correct, if you use transactions, you do not need to manage a
> timestamp.  This is because GAE has its own timestamp on each entity
> group.  When you load an entity in a transaction, GAE checks this
> timestamp.  When you commit, it checks the timestamp again - and if
> something changed, you get a ConcurrentModificationException.  By
> running your transaction in a retry loop and checking for
> ConcurrentModificationException, you can safely ensure that non-stale
> data is written.
>
> Note that this isn't too far off from a description of what happens
> when you do a non-transactional put().  It's just that the transaction
> and retry loop are performed within the datastore itself.  Creating an
> explicit transaction just provides the opportunity for your business
> logic to get "in the loop" so to speak.
>
> Jeff
>
> On Thu, Apr 7, 2011 at 7:09 AM, Peter Backx  wrote:
>> Hi Ikai,
>>
>> Could you expand your answer a little? Do you mean that I don't need to
>> manage a timestap/version if I use transactions? Or do you mean I should use
>> transactions to combine a read (to check for a changed timestamp/version)
>> with a write?
>>
>> If I don't manage the timestamp myself, how does AppEngine know another
>> process change the data since the last read? part of the key?
>>
>> Sorry for those beginner questions, I started using the datastore via the
>> JDO API with a relational background, but it looks it isn't always the best
>> fit for typical datastore issues. Objectify looks much better as it is
>> specifically designed for it.
>>
>>
>> Thanks every one for your answers
>>
>> Peter
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Google App Engine for Java" group.
>> To post to this group, send email to google-appengine-java@googlegroups.com.
>> To unsubscribe from this group, send email to
>> google-appengine-java+unsubscr...@googlegroups.com.
>> For more options, visit this group at
>> http://groups.google.com/group/google-appengine-java?hl=en.
>>
>

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



Re: [appengine-java] Best practice for multithreaded access/update to entity

2011-04-07 Thread Peter Backx
Perfect, exactly the info I needed!
Thanks a lot Jeff.

Peter

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