views:

28

answers:

1

I have observed the following: (Odp is a model)

o = Odp.get(odpKey)
o.foo = 0
foo()
assert o.foo == 1 # fails

def foo():
    o = Odp.get(odpKey)
    o.foo += 1
    o.put()

It looks like the first copy of o isn't refreshed when it's underlying datastore representation is updated. So, what is the preferred way to refresh it?

I was thinking something like:

o = Odp.get(odpKey)
o.foo = 0
foo()
o = Odp.get(o.key())
assert o.foo == 1 # win

Or is there a better way?

+4  A: 

t looks like the first copy of o isn't refreshed when it's underlying datastore representation is updated.

Correct: there are two completely independent objects in memory during the execution of function foo -- both happen to be bound to barenames equal to o, in different scopes, but that's an irrelevant detail (just further confusing things;-).

o = Odp.get(odpKey)
o.foo = 0
foo()
o = Odp.get(o.key())
assert o.foo == 1 # win

"win" only the first time -- because the o.foo = 0 only affects a copy that's never put to the DB, and then o is rebound to a third copy just gotten from the DB, then o.foo will be 1 the first time (if the foo attribute defaults to 0) but not on subsequent attempts as it keeps increasing by one every time. You need an o.put() before the call to foo() to make the o.foo = 0 assignment have any meaning or sense whatsoever.

A better idea is to have the foo function accept an optional argument (the object in question) and have it get a fresh copy only if it didn't receive that argument; and then in any case return the object it's working on. IOW, you'd have:

o = Odp.get(odpKey)
o.foo = 0
o = foo(o)
assert o.foo == 1  # always OK

def foo(o=None):
  if o is None:
    o = Odp.get(odpKey)
  o.foo += 1
  return o

You might add an o.put() somewhere, but normally it's better to save only when a set of related changes have all been applied to the in-memory copy. Doing essentially all the work on a single in-memory copy saves a lot of roundtrips to the DB and thereby speeds your app up by a lot.

Alex Martelli