coto
coto

Reputation: 2325

App Engine: ReferencePropertyResolveError in Google App Engine?

Please help me to understand Why this error on App Engine (Python 2.5, High Replication) ?

Traceback (most recent call last):
File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/_webapp25.py", line 703, in __call__ 
    handler.post(*groups)
File "/base/data/home/apps/s~apptest/1.354937136776013205/main.py", line 963, in post
    get_purchases_for_user(pur.user, pur.car.model)
File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/__init__.py", line 3592, in __get__
    reference_id.to_path())
ReferencePropertyResolveError: ReferenceProperty failed to be resolved: [u'User', 374836L]

Context: The application is about recommendations to buy cars.

When this happens: Around 2 times per each 100 transactions approximately, so really I don't know when nor why.

Where the object pur in the code is defined as:

allPurchases = models.Purchase.all()
for pur in allPurchases:
   car = get_purchases_for_user(pur.user, pur.car.model)

Also I put this code before and I got the same error, of course referencing to this line

logging.error("Object user: %s, Car Model %s" % {str(pur.user), pur.car.model})

So, the problem is not in the get_purchases_for_user function

And these are the models in the datastore:

class User(db.Model):
    username = db.StringProperty(
        required=True)
    name = db.StringProperty(
        required=True)
    email = db.EmailProperty(
        required=True)
    password = db.StringProperty(
        required=True)

class Car(db.Model):
    model = db.StringProperty()
    name = db.StringProperty()
    year = db.DateTimeProperty()

class Purchase(db.Model):
    user = db.ReferenceProperty(User,
        collection_name='recommendations')
    car = db.ReferenceProperty(Car,
        collection_name='recommendations')
    when = db.DateTimeProperty(
        auto_now=True)

Upvotes: 1

Views: 1097

Answers (2)

Nick Johnson
Nick Johnson

Reputation: 101139

Your entity has a ReferenceProperty to a User entity that doesn't exist - most likely because it has been deleted. You can add code to catch this particular exception and deal with it in whatever way is appropriate in your application.

Upvotes: 4

Sologoub
Sologoub

Reputation: 5352

I'm leaning towards the problem being the datastore's high replication and lack of guaranteed consistancy. From google documentation:

However, in the High Replication datastore, queries across entity groups (in other words, non-ancestor queries) may return stale results. In order to return strongly consistent query results in the High Replication environment, you need to query over a single entity group. This type of query is called an ancestor query.

Ancestor queries work because entity groups are a unit of consistency: all operations are applied to the entire group. Ancestor queries won't return data until the entire entity group is up to date. Thus, the data returned from ancestor queries on entity groups is strongly consistent.

If your application relies on strongly consistent results for certain queries, you may have to change the way your application stores entities. This page discusses best practices for working with data stored in the High Replication Datastore. Let's look at how this works using the sample guestbook applications for Master/Slave and High Replication Datastores, respectively.

So effectively, you could be querying for something that just got written, but has not propagated across the entire datastore. As the result, when you reference the property it's as if it never existed or got deleted.

Looks like you are using .all() to retrieve the data. I'd suggest re-writing it to use GQL and the ancestor queries if possible. Or maybe restricting data in time to allow for propagation. Docs on ancestor queries: http://code.google.com/appengine/docs/python/datastore/queries.html#Ancestor_Queries

Upvotes: 3

Related Questions