Create-or-Err with Objectify

2019-02-20 01:33发布

I'm getting started with Google App Engine, and I'm using Objectify. How do I create a root entity in the data store, but err if it already exists? I didn't find anything built in for this (e.g. DatastoreService.put() and therefore ofy().save() will overwrite an existing entity instead of err). The simple technique I am used to is to do this in a transaction:

  1. Err if already exists
  2. Save

However, that is not idempotent; it would err in step 1 if the transaction executes twice. Here is the best I've come up with so far, not in a transaction:

  1. Err if already exists
  2. Save
  3. Fetch
  4. Err if it's not the data we just created

Or, if I don't mind two requests to save the same data both succeeding, I can skip the initial lookup:

  1. Fetch
  2. Report success if it's the same data we are about to create
  3. Err if already exists, but is not the same data we are about to create
  4. Save

That is doable, but it gets a little bulky to accomplish what I thought would be a very simple operation. Is there a better way?

1条回答
一纸荒年 Trace。
2楼-- · 2019-02-20 02:25

This should guarantee consistent behavior:

final String id = // pick the unique id
final long txnId = // pick a uuid, timestamp, or even just a random number

ofy().transact(new VoidWork() {
    public void vrun() {
        Thing th = ofy().load().type(thing.class).id(id).now();
        if (th != null) {
            if (th.getTxnId() == txnId)
                return;
            else
                throw ThingAlreadyExistsException();
        }

        th = createThing(id, txnId);
        ofy().save().entity(th);
    }
});
查看更多
登录 后发表回答