Если мы запускаем транзакцию для удаления сложного объекта в appengine, и к объекту прикреплены некоторые ссылки на большие двоичные объекты, которые необходимо удалить, у нас возникает проблема. Если мы просто удалим большие двоичные объекты, транзакция может завершиться неудачно, но большие двоичные объекты исчезнут, потому что хранилище больших двоичных объектов работает независимо (это противоречит идее транзакций).
Теперь у нас есть этот классный новый NDB, у которого есть контекстный кеш без документированного API (?), Который мог бы решить проблему.
Инструментальный ящик:
- ndb.get_context () (недокументировано в ссылке на функцию ndb)
ndb_context.call_on_commit (delete_blobs_call_on_commit)
def delete_blobs_call_on_commit(): ndb_context = ndb.get_context() blobstore.delete(ndb_context.list_of_blobkeys_to_delete) # OR: taskqueue.add(url+ndb_context.list_of_blobkeys_to_delete)
Задача: прикрепить blobkeys для удаления во время транзакции к объекту контекста и удалить их после транзакции.
Обновление: call_on_commit () не разрешает операции с базой данных (которые могут включать blobstore.delete, но не пробовали) и выдает ошибку BadRequestError: невозможно начать новую операцию в завершенной транзакции, поэтому единственное решение действительно может быть очередь задач.
Обновление: можно вызвать функцию с помощью декоратора @ ndb.non_transactional из функции, зарегистрированной с помощью call_on_commit (). Таким образом, можно попытаться удалить капли при успешной фиксации и надеяться, что у вас нет исключений, которые могут привести к потере.
Вопросы: как безопасно использовать контекстный кеш? Как вы решили проблему с удалением больших двоичных объектов?
call_on_commit
, если вы украсите ее:@ndb.transactional(xg=True, propagation=ndb.TransactionOptions.MANDATORY)
. По крайней мере, до сих пор этот подход работал в моих экспериментах. - person Marc   schedule 12.06.2014