如何使用ndb使blobstore删除操作事务安全?

时间:2013-07-16 08:23:06

标签: google-app-engine blobstore app-engine-ndb

如果我们启动一个事务来删除appengine上的一个复杂对象,并且该对象附加了一些需要删除的blob引用,那么我们就会遇到问题。如果我们只是删除blob,那么事务可能会失败,但blob会消失,因为blobstore独立工作(这违背了事务的想法)。

现在我们有了这个很酷的新NDB,它有一个上下文缓存,没有可以解决问题的文档API(?)。

Toolchest:

  • 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:无法在已完成的事务中启动新操作,因此唯一的解决方案可能就是任务问题。

更新:可以使用call_on_commit()注册的函数调用@ ndb.non_transactional装饰器的函数。因此,可以尝试在提交成功时删除blob,并希望您没有会导致孤立的异常。

问题:如何安全地使用上下文缓存?你是如何解决blob删除问题的?

2 个答案:

答案 0 :(得分:1)

AFAIK blob实际上在数据存储区中有一个表示,因此您可以在事务中使用它们。

要安全地使用上下文缓存,请对这些标志使用常规的Model / Key get()和put()操作:use_memcache = False,use_datastore = False,use_cache = True。您还可以将这些标志放在模型定义中,作为类变量。

答案 1 :(得分:0)

使用blob无意义删除实体组的一种方法可能是在没有事务的情况下进行可重复的容错删除操作(幂等操作)。

  1. 将实体/祖先标记为已删除,放置(重要的是确保没有人可以再使用它)
  2. 从叶子到父母的交易中删除没有交易
  3. 任何时候发生错误,中止
  4. 用户(查看已删除的项目)或系统(taskqueue)可以稍后重试删除
  5. 删除必须能够跳过已删除的引用为幂等
  6. 有人能看到这种方法存在问题吗?