#python #google-app-engine #google-cloud-datastore
#python #google-app-engine #google-cloud-хранилище данных
Вопрос:
У меня есть следующий код, который мне нужно запустить в транзакции с сериализуемым уровнем изоляции, который, согласно документации, поддерживается хранилищем данных Google:
class Test(ndb.Model):
child_ids = ndb.KeyProperty(repeated=True)
@classmethod
@ndb.transactional()
def add(cls, parent_id, child_id):
key = ndb.Key(cls, unicode(child_id.kind()), parent=parent_id)
# 1
x = key.get()
# 2
if x:
# 3
if child_id not in x.child_ids:
x.child_ids.append(child_id)
x.put()
else:
# 4
cls(key=key, child_ids=[child_id]).put()
«добавить» вызывается дважды в двух разных _post_put_hook с одним и тем же родительским идентификатором и одним и тем же дочерним идентификатором.kind().
Чего я ожидал бы, так это того, что создается только один объект с 2 дочерними идентификаторами (или одна из транзакций должна завершиться неудачей).
Вместо этого происходит то, что последняя транзакция для фиксации «выигрывает», а child_ids всегда содержит только один элемент. Транзакция в конечном итоге выполняется переплетенной следующим образом:
T1#1
T2#1
T1#2
T1#4
T2#2
T2#4 <-in a serializable transaction this should fail
Что не так с моим кодом?