I posted the question on Stackoverflow and the consensus is that it
should be wrapped in a transaction.
http://stackoverflow.com/questions/3782296/java-google-appengine-sharded-counters-without-transactions

I also opened an Appengine issue (is this the right way to report
issues in documentation?):
http://code.google.com/p/googleappengine/issues/detail?id=3778&q=sharded&colspec=ID%20Type%20Status%20Priority%20Stars%20Owner%20Summary%20Log%20Component


On Sep 21, 12:24 pm, Doug Daniels <daniels.doug...@gmail.com> wrote:
> I'm going through the Sharded Counters example in 
> Java:http://code.google.com/appengine/articles/sharding_counters.html
>
> I have a question about the implementation of the increment method. In
> python it explicitly wraps the get() and increment in a transaction.
> In the Java example it just retrieves it and sets it. I'm not sure I
> fully understand the Datastore and transactions but it seems like the
> critical update section should be wrapped in a datastore transaction.
> Am I missing something?
>
> Original code:
> public void increment() {
>     PersistenceManager pm = PMF.get().getPersistenceManager();
>
>     Random generator = new Random();
>     int shardNum = generator.nextInt(NUM_SHARDS);
>
>     try {
>       Query shardQuery = pm.newQuery(SimpleCounterShard.class);
>       shardQuery.setFilter("shardNumber == numParam");
>       shardQuery.declareParameters("int numParam");
>
>       List<SimpleCounterShard> shards =
>           (List<SimpleCounterShard>) shardQuery.execute(shardNum);
>       SimpleCounterShard shard;
>
>       // If the shard with the passed shard number exists, increment
> its count
>       // by 1. Otherwise, create a new shard object, set its count to
> 1, and
>       // persist it.
>       if (
>
> Transactional code:
>
> public void increment() {
>     PersistenceManager pm = PMF.get().getPersistenceManager();
>
>     Random generator = new Random();
>     int shardNum = generator.nextInt(NUM_SHARDS);
>
>     try {
>       Query shardQuery = pm.newQuery(SimpleCounterShard.class);
>       shardQuery.setFilter("shardNumber == numParam");
>       shardQuery.declareParameters("int numParam");
>
>       List<SimpleCounterShard> shards =
>           (List<SimpleCounterShard>) shardQuery.execute(shardNum);
>       SimpleCounterShard shard;
>
>       // If the shard with the passed shard number exists, increment
> its count
>       // by 1. Otherwise, create a new shard object, set its count to
> 1, and
>       // persist it.
>       if (shards != null && !shards.isEmpty()) {
>             Transaction tx = pm.currentTransaction();
>
>         try {
>             tx.begin();
>                         //I believe in a transaction objects need to be 
> loaded by ID (can't
> use the outside queried entity)
>                         Key shardKey =
> KeyFactory.Builder(SimpleCounterShard.class.getSimpleName(),
> shards.get(0).getID())
>                         shard =  pm.getObjectById(SimpleCounterShard.class, 
> shardKey);
>                         shard.setCount(shard.getCount() + 1);
>             tx.commit();
>         } finally {
>             if (tx.isActive()) {
>                 tx.rollback();
>             }
>         }
>
>       } else {
>         shard = new SimpleCounterShard();
>         shard.setShardNumber(shardNum);
>         shard.setCount(1);
>       }
>
>       pm.makePersistent(shard);
>     } finally {
>       pm.close();
>     }
>   }
>
>
>
>
>
>
>
> }

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

Reply via email to