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