У меня есть бизнес-проблема: у родительского объекта есть потомок дочернего объекта.Дочерняя сущность имеет значение, которое должно быть уникальным, поэтому сущность ChildLookup существует для обеспечения этой уникальности.Чтобы абстрагировать некоторые вещи, сущности помещают / удаляют, были помещены в свои собственные методы, и оба имеют операторы пакетной обработки / транзакции как часть своей логики.
В Python (используя эту библиотеку ), когда структура подобна этой, все в порядке:
# assuming ('Parent', 11), ('Parent', 11, 'Child', 'foo') (with value 'bar'), and ('ChildLookup-foo', 'bar') all exist
def put_parent(c):
p2 = c.get(c.key('Parent', 22))
if p2 is None:
p2 = Entity(c.key('Parent', 22))
c.put(p2)
def put_child(c):
with c.transaction():
e2 = Entity(c.key(*p2.key.flat_path, 'Child', 'foo'))
e2['__val'] = 'bar'
el2 = c.get(c.key('ChildLookup-foo', e2['__val']))
if el2 is not None:
raise ValueError('insert would create duplicate')
el2 = Entity(c.key('ChildLookup-foo', 'val'))
c.put(el2)
c.put(e2)
c = google.cloud.datastore.Client()
with c.transaction():
put_parent(c)
put_child(c)
Попытка выполнить это приведет к правильному поведению: возникнет исключение, и ни один из p2 или e2 не будет вставлен.Однако я могу изменить put_parent так:
def put_parent():
with c.transaction(): # only actual change. can also be c.batch()
p2 = c.get(c.key('Parent', 22))
if p2 is None:
p2 = Entity(c.key('Parent', 22))
c.put(p2)
Когда я делаю это таким образом, вставляется p2, несмотря на откат второй транзакции.Для меня это неожиданно: я ожидаю, что откат будет ограничен только самой внутренней транзакцией (или пакетом), или я ожидаю, что откат повлияет на все дочерние транзакции самой внешней транзакции (или пакета).
Конечно, в приведенном выше тривиальном примере с игрушкой я мог просто вынуть внутренние партии и управлять ими с верхнего уровня.Но смысл их использования в методах заключается в том, что я иногда мог бы вызывать их по отдельности без одинаковых гарантий от метода, который вызывает их оба, и я хотел бы, чтобы бизнес их требований к транзакционности был не важен для потребителя этих методов.,Есть ли шаблон дизайна или какая-нибудь библиотека Python Google Cloud Datastore, которая позволила бы мне делать то, что я пытаюсь сделать?