TransactionとEntity Groupについての理解で言及されていたことを試してみたのですが、どうも微妙に違うような?
つまりTransaction内では、(多分Keyに関する操作がある場合には)暗黙のうちに「Key.from_path(u'UserAccount', u'tagomoris')を親とするEntity Groupに対する操作」として扱われている、ということだろう。
このエントリの add_useraccount() が動作するのは、get_by_key_name に成功した場合は u = UserAccount.get_by_key_name(name) のEntity Group のみをTransaction 内で触っていることになり、get_by_key_name に失敗した場合は u = UserAccount(key_name=name, fullname=fullname) のEntity Group のみへの操作となるからな気がします。参照するEntity Groupと作成するEntity Groupは確かに別物で、Transaction内で同時に触ることができないってのも真なのですが、この例の場合だと参照と作成は同時に起きないってのがミソでしょう。
ということで、以下のようなコードを書けば、"Cannot operate on different entity groups in a transaction"となります。
def make_shadow(body_name, fullname): u = UserAccount.get_by_key_name(body_name) if u is None: raise db.Rollback u = UserAccount(key_name=u.key().name() + "_shadow", fullname=fullname) u.put() return u user = UserAccount(key_name="hiratara", fullname="Masahiro Honma") user.put() new_user = db.run_in_transaction(make_shadow, "hiratara", "Shadow Honma")
BadRequestError: Cannot operate on different entity groups in a transaction: (kind='UserAccount', name='hiratara') and (kind='UserAccount', name='hiratara_shadow').