non
deterministic
bug
or
ndb?
Class Zoo(ndb.Model):
my_cool_monkeys = ndb.JsonProperty(repeated=True)
1 - Will this work?
monkeys = zoo.my_cool_monkeys
print monkeys[0][‘name’]
print monkeys[1][‘name’]
1 - Will this work? Yup.
monkeys = zoo.my_cool_monkeys
print monkeys[0][‘name’]
print monkeys[1][‘name’]
2 - Will this work?
monkeys = zoo.my_cool_monkeys
zoo.put_async()
print monkeys[0][‘name’]
print monkeys[1][‘name’]
2 - Will this work? Yup.
monkeys = zoo.my_cool_monkeys
zoo.put_async()
print monkeys[0][‘name’]
print monkeys[1][‘name’]
3 - Will this work?
monkeys = zoo.my_cool_monkeys
zoo.put_async()
any_ndb_key.get()
print monkeys[0][‘name’]
print monkeys[1][‘name’]
3 - Will this work? NO!
monkeys = zoo.my_cool_monkeys
zoo.put_async()
any_ndb_key.get()
print monkeys[0][‘name’]
print monkeys[1][‘name’]
TypeError:
'_BaseValue' object
is not
subscriptable
Why?
When ndb sees the synchronous
.get()
Why?
When ndb sees the synchronous
.get()
it remembers to go through with the earlier
.put_async()
Why?
When ndb sees the synchronous
.get()
it remembers to go through with the earlier
.put_async()
which mutates the referenced items into _BaseValues :(
This will work
zoo.put_async()
any_ndb_key.get()
monkeys = zoo.my_cool_monkeys # this moved down
print monkeys[0][‘name’]
print monkeys[1][‘name’]
Reading from the entity converts from _BaseValue correctly.
This will work
zoo.put_async()
any_ndb_key.get()
print zoo.my_cool_monkeys[0][‘name’]
print zoo.my_cool_monkeys[1][‘name’]
Or better yet,
always read from
the entity.
non
deterministic
bug
or
ndb?
This _BaseValue TypeError happened
occasionally
on homepage load.
non
deterministic
bug
or
ndb?
So where’s the
non determinism?
non
deterministic
bug
or
ndb?
So where’s the
non determinism?
No where.
non
deterministic
bug
or
ndb?
So where’s the
non determinism?
No where.
We thought it was non deterministic because we didn’t
know how to repro this TypeError bug.
Until we realized the TypeError happened every time devappserver restarted.
Which clears the instance cache...
Until we realized the TypeError happened every time devappserver restarted.
Which clears the instance cache...
...Which means the FMS does a synchronous get()
https://code.google.com/p/appengine-ndb-experiment/issues/detail?id=208
http://phabricator.khanacademy.org/D7275
And yes, this monkeys in an ndb quiz format is a hat tip to: http://bjk5.com/post/78634742389/three-minute-quiz-app-engine-datastore-performance
Thanks, ndb!
Bonus - Will this work?
monkeys = zoo.my_cool_monkeys
zoo.put()
print monkeys[0][‘name’]
print monkeys[1][‘name’]
Bonus - Will this work? NO!
monkeys = zoo.my_cool_monkeys
zoo.put()
print monkeys[0][‘name’]
print monkeys[1][‘name’]
TypeError:
'_BaseValue' object
is not
subscriptable
Bonus - Will this work? NO!
monkeys = zoo.my_cool_monkeys
zoo.put()
print monkeys[0][‘name’]
print monkeys[1][‘name’]
# Breaks for the same reason as scenario 3
TypeError:
'_BaseValue' object
is not
subscriptable