BlueBoy
BlueBoy

Reputation: 856

Will two entities get written to datastore with this endpoint?

I have an endpoint method that first uses a query to see if an entity with certain params exists, and if it does not it will create it. If it exists, I want to increase a counter in the variable:

Report report = ofy().load().type(Report.class)
    .filter("userID", userID)
    .filter("state", state).first().now();

if (report == null) { 
    //write new entity to datastore with userID and state
} else {
    //increase counter in entity +1
    report.setCount(report.count+1)
    //save entity to datastore
}

My question is, what if someone clicks a button to execute the above endpoint with the same params very rapidly, what will happen? Will two identical Report entities get written to the datastore? I only want to make sure one is written.

Upvotes: 0

Views: 45

Answers (1)

stickfigure
stickfigure

Reputation: 13556

By itself this code is not safe and has a race condition that will allow multiple Reports to be created.

To make this safe, you need to run the code in a transaction. Which means you must have an ancestor query (or convert it to a simple primary key lookup). One option is to give Report a @Parent of the User. Then you can so something like this:

ofy().transact(() -> {
    Report report = ofy().load().type(Report.class)
        .ancestor(user)
        .filter("state", state).first().now();

    if (report == null) { 
        //write new entity to datastore with userID and state
    } else {
        //increase counter in entity +1
        report.setCount(report.count+1)
        //save entity to datastore
    }
});

Upvotes: 1

Related Questions