after reading google datastore concepts/theory started using go datastore package
scenario: kinds user , linkedaccount require every user has 1 or more linked accounts (yay 3rd party login). strong consistency, linkedaccounts children of associated user. new user creation involves creating both user , linkedaccount, never one.
user creation seems perfect use case transactions. if, linkedaccount creation fails, transaction rolls fails. doesn't seem possible. goal create parent , child within transaction.
according docs
all datastore operations in transaction must operate on entities in same entity group if transaction single group transaction
we want new user , linkedaccount in same group, me sounds datastore should support scenario. fear intended meaning operations on existing entities in same group can performed in single transaction.
tx, err := datastore.newtransaction(ctx) if err != nil { return err } incompleteuserkey := datastore.newincompletekey(ctx, "user", nil) pendingkey, err := tx.put(incompleteuserkey, user) if err != nil { return err } incompletelinkedaccountkey := datastore.newincompletekey(ctx, "githubaccount", incompleteuserkey) // tried pendingkey parent, separate struct type _, err = tx.put(incompletelinkedaccountkey, linkedaccount) if err != nil { return err } // attempt commit if _, err := tx.commit(); err != nil { return err } return nil from library source clear why doesn't work. pendingkey's aren't keys , incomplete keys can't used parents.
is necessary limitation of datastore or of library? experienced type of requirement, did sacrifice strong consistency , make both kinds global?
for google-ability:
- datastore: invalid key
- datastore: cannot use pendingkey type *"google.golang.org/cloud/datastore".key
one thing note transactions in cloud datastore api can operate on 25 entity groups, doesn't answer question of how create 2 entities in same entity group part of single transaction.
there few ways approach (note applies use of cloud datastore api, not gcloud-golang library):
use (string) name parent key instead of having datastore automatically assign numeric id:
parentkey := datastore.newkey(ctx, "parent", "parent-name", 0, nil) childkey := datastore.newincompletekey(ctx, "child", parentkey)make explicit call
allocateidshave datastore pick numeric id parent key:incompletekeys := [1]*datastore.key{datastore.newincompletekey(ctx, "parent", nil)} completekeys, err := datastore.allocateids(ctx, incompletekeys) if err != nil { // ... } parentkey := completekeys[0] childkey := datastore.newincompletekey(ctx, "child", parentkey)
Comments
Post a Comment