transactions - App Engine: Mechanics of creating a unique entity if it doesn't exist -
we have issue want lazily create entity if not exist. there discussion going on how , clarify things around app engine transactions. limit query single entity group transactions.
i using go in examples, hope code clear enough non-go programmers.
my understanding transaction, on single entity group, succeed if entity group not modified externally during transaction. 'entity group timestamp' indicating when entity group changed stored in root entity of entity group. during transaction current 'entity group timestamp' read , transaction can succeed if hasn't changed end of transaction.
key := datastore.newkey(c, "counter", "mycounter", 0, nil) count := new(counter) err := datastore.runintransaction(c, func(c appengine.context) error { err := datastore.get(c, key, count) if err != nil && err != datastore.errnosuchentity { return err } count.count++ _, err = datastore.put(c, key, count) return err }, nil)
in example above (taken https://cloud.google.com/appengine/docs/go/datastore/transactions) there 2 non-error cases, can see:
- the succeeds , 'entity group timestamp' on counter can used ensure no other transactions update counter during transaction.
- the fails
errnosuchentity
, put used store counter first time.
in second case possible identical transaction running. if both transactions' return errnosuchentity
how datastore ensure 1 put succeeds? expect there no "entity group timestamp" in datastore test against?
does transaction know needs test non-existence of counter in order put , entire transaction succeed?
is there chance in case 2 transactions succeed , 1 put overwrite other?
if there documentation, or videos etc, around mechanism controls love read it.
to answer question must dig deeper, source code of dev datastore, fortunately documented, take @ livetxn._grabsnapshot
:
gets snapshot reference, creating if necessary.
if no snapshot has been set reference's entity group, snapshot taken , stored future reads (this sets read position), , concurrent_transaction exception thrown if no longer have consistent snapshot.
so edge case different speculating: both transactions create fresh timestamp, , things work usual. in case putting forth, 2nd transaction retry, , counter incremented twice.
there's no in-depth documentation how transactions work i'm aware of, @ least not this deep, source code not that hard read; in instance can follow trail of concurrent_transaction
error.
Comments
Post a Comment