2015-07-17 3 views
3

После прочтения о Google Datastore концепции/теории я начал использовать Go datastore packageDatastore: создать родительский и дочерний объект в транзакции группы объектов?

Сценарий: Виды User и LinkedAccount требуют, чтобы каждый пользователь имеет один или несколько связанных счетов (яй 3-й вход партии). Для сильной согласованности LinkedAccounts будут дочерними элементами связанного пользователя. Создание нового пользователя затем включает в себя создание как пользователя, так и LinkedAccount, а не только одного.

Создание пользователя похоже на идеальный вариант использования для транзакций. Если, скажем, создание LinkedAccount завершается неудачно, транзакция откатывается с ошибкой. В настоящее время это не представляется возможным. Цель состоит в том, чтобы создать родителя, а затем ребенка в транзакции.

Согласно документации

операций Всех Datastore в операции должны работать на лицах в ту же группу объектов, если сделка является одной транзакцией группы

Мы хотим, чтобы новый User и LinkedAccount быть в одной группе, поэтому мне кажется, что Datastore должен поддерживать этот сценарий. Я опасаюсь, что предполагаемое значение состоит в том, что операции с существующими объектами в одной и той же группе могут выполняться в одной транзакции.

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) 
// also tried PendingKey as parent, but its a separate struct type 
_, err = tx.Put(incompleteLinkedAccountKey, linkedAccount) 
if err != nil { 
    return err 
} 
// attempt to commit 
if _, err := tx.Commit(); err != nil { 
    return err 
} 
return nil 

От library source его понятно, почему это не работает. PendingKey не являются ключами, а неполные ключи не могут использоваться в качестве родителей.

Является ли это необходимым ограничением хранилища данных или библиотеки? Для тех, кто сталкивался с этим типом требований, вы просто пожертвовали сильной консистенцией и сделали оба вида глобальными?

Для Google-способности:

  • датасторе: недействительный ключ
  • датасторе: не может использовать pendingKey как тип * "google.golang.org/cloud/datastore" .key

ответ

3

One Следует отметить, что транзакции в API облачного хранилища данных can operate on up to 25 entity groups, но это не отвечает на вопрос о том, как создать два объекта в одной и той же группе сущностей, как часть одной транзакции.

Есть несколько способов приблизиться к этому (обратите внимание, что это относится к любому использованию API Cloud Datastore, а не только gcloud-golang библиотеки):

  1. Используйте имя (строки) для родительского ключа вместо того, чтобы Datastore автоматически присвоит числовой идентификатор:

    parentKey := datastore.NewKey(ctx, "Parent", "parent-name", 0, nil) 
    childKey := datastore.NewIncompleteKey(ctx, "Child", parentKey) 
    
  2. сделать явный вызов AllocateIds иметь Datastore выбрать числовой идентификатор родительского ключа:

    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) 
    
+0

Спасибо за ответ.Я полагаю, что мой вопрос действительно сводится к тому, что «готовые или неполные ключи могут использоваться как своего рода« обещание »в транзакции», и кажется, что ответ отрицательный. Я предпочитаю ваше предложение, используя AllocateIds bc. Мне бы хотелось, чтобы Datastore выбирал числовой идентификатор, но недостатком AllocateIds недоступно в транзакциях. Я изучу эти подходы и вернусь – dghubble

+0

Да, это хороший способ подвести итог, и вы правы, что в настоящее время не поддерживается. Что касается AllocateIds: он не транзактивен в том смысле, что распределение не откат, если транзакция завершилась неудачей, но это не мешает вам позвонить, пока транзакция активна. Если транзакция не удалась, вы просто в конечном итоге выделяете идентификатор, который не используется - не имеет большого значения. –

+0

В этот уик-энд я взял подход AllocateIDs к транзакциям, требующим завершения ключа, и решил, что мне вряд ли понадобится вернуть выделенные, но неиспользуемые идентификаторы, потому что пространство настолько велико. – dghubble

Смежные вопросы