Google App Engine Datastore: Dealing with eventual consistency


I am developing a GAE web application and I need to create and remove associations among instances of two Entities which have no ancestor relationship (also consider the same instance may have multiple associations that may vary in time while the ancestor relationship, once created, can't be removed). I have experienced the 'eventual consistency' policy which means data in my web page are not refreshed coherently with the relationships I am creating/removing. However I have seen that by executing the put() method twice the consistency seems to be force.

This is compliant with the "Eventual Consistency" definition which states that "... provided no new updates are made ..." data will eventually be consistent and, since I am making another update (actually the same two times) I guess the system forces the consistency.

Am I right? Is there any other more elegant way of doing it?

<strong>Update: My AIM</strong>

Consider I have a list of entities of type A, it doesn't matter what they actually represent, let's say they represent the main entities of my business I have a list of another entities of type B representing services the entities of type A can rely on. it is a many to many relationship so A service b can be used by many entities a of type A An entity a can be served by many services b of type B

I have a web page allowing me to create such relationship, (a Jinja2 template with a Jquery Ajax callback from the client side and a webapp2 python request handler relying on the datastore in the server side). When a relationship is removed from the datastore I refresh the data by making another query on the a entity and depicting the list of b keys it has related. In this case I still see the removed b.key in the list of b keys related to a. Which is not what I would expect.

<strong>UPDATE: SOME CODE</strong>

here is the model

class A(ndb.Model): name = ndb.StringProperty() services = ndb.KeyProperty(repeated=True) class B(ndb.Model): name = ndb.StringProperty() servedEntities = ndb.KeyProperty(repeated=True)

here is the code I use to create the relationship

a.services.append(b.key); b.servedEntities.append(a.key); a.put() b.put()

here is the code I use to remove the relationship

a.services.remove(b.key); b.servedEntities.remove(a.key); a.put() b.put()

There is no ancestor relationship between a and b (and there can not be) After the relationship removal I if retrieve again a from the Datastore I can still see b.key listed in a.services


The answer to your question lies in this statement:


When a relationship is removed from the datastore I refresh the data by making another query on the a entity.


Why do you need a new query?

Let's say a user subscribed to services x, y and z. Now a user tells you to drop service z from the list. You go to the Datastore and make the necessary change. Instead of running a new query, however, which may still show z among the returned entities, you can simply remove z from your user entity on the client side and update the UI accordingly.

This is obviously a simplified example. I faced a similar challenge when I wrote the school scheduling app, which had a more complex use case - a single change may affect many entities in the selected time period (e.g. "schedule a lesson every school day until the end of the quarter"), so I was tempted to simply run a new query to refresh the schedule view. Obviously, I ran into the eventual consistency problem magnified by the fact that sometimes dozens of entities had to be created. Then I realized that I already have all the data that I need to refresh the view without running a new query. It's a bit more code, but it's a clean and reliable solution.


  • Why is Controller.Url null when I unit test my action?
  • Why does my arrow function have a prototype property?
  • How to open the ios Native dialer app from my App
  • Does a developer have to pay for publishing a SaaS app on Windows Azure Marketplace?
  • substr doesn't work fine with utf8
  • When an object has the same name as its class in a VB project, how do I rename the object without al
  • How to return only text after a comma in a string
  • Invalid Django TIME_ZONE
  • All I get is a blank page when I visit localhost:9080
  • Mongoid doesn't update position field
  • Non-blocking mlock()
  • using copy in postgresql?
  • How to get Angular.js binding tags safely past Python's Jinja2?
  • Why is Azure giving me random 500 errors?
  • Why is the line of wss-plot (for optimizing the cluster analysis) looks so fluctuated?
  • Ember, working with a model
  • CMake with regarding generated files
  • Delphi MainFormOnTaskBar Modal windows bug
  • Why context.Wait in StartAsync didn't stop the dialog
  • Dynamically create controls in android using Kotlin
  • Set a page title from a PartialView [duplicate]
  • Octopress --> Heroku error env: bundle: no such file or directory
  • Winston logger not write to file
  • Sprite animation wobbly / jumping in IE11
  • Different sized images (with the same name) in one drawable folder
  • How to manipulate content of a comment with Apache POI
  • Optimization of optim() in R ( L-BFGS-B needs finite values of 'fn')
  • How convert html to BBcode in C#
  • Is there a better way for handling SpatialPolygons that cross the antimeridian (date line)?
  • Problems to understand DXGI DirectX 11 Desktop Duplication to get a Buffer or Array
  • C++ STL stack pop operation giving segmentation fault
  • How to use Streams api peek() function and make it work?
  • VSTS work items list through REST API
  • How to decleare char *const argv[] in swift [duplicate]
  • How to encrypt Connectionstring written in web.config from codebehind?
  • How to get rgb from transparent pixel in js
  • Can someone explain this Java code (formatting the output using System.out.format) to me?
  • WPF custom control and direct content support
  • What does the “id” field in an Android “Google Play Music” broadcast intent correspond to?
  • XSLT Transformation to validate rules in XML document