Search code examples
pythongoogle-app-enginegoogle-cloud-platformapp-engine-ndb

Cloud NDB: transactionally put() multiple entities


There are situations where we must save two or more datastore entities at once (either both entities are saved or neither is saved). For my example, I want to create a UserProfile entity when a User entity is created.

from entities import User, UserProfile

def create_user_and_profile():
    # First, create the User entity
    user = User(email=email, password=password_hash)
    user.put()

    # Then, create a UserProfile entity
    # that takes a user.key as parent
    user_profile = UserProfile(parent=user.key)
    user_profile.put()

The function above is not atomic. It is possible that only one or neither of the entities are saved successfully.

How can I make this atomic?


Solution

  • there's transactional decorator in ndb you can use. If any of the records would fail to be saved, none of them will:

    from google.cloud import ndb
    
    
    @ndb.transactional()
    def create_user_and_profile():
        # First, create the User entity
        user = User(email=email, password=password_hash)
        user.put()
    
        # Then, create a UserProfile entity
        # that takes a user.key as parent
        user_profile = UserProfile(parent=user.key)
        user_profile.put()
    
    with ndb_client.context(): # ndb client instance
        create_user_and_profile()