3

appengine で複雑なオブジェクトを削除するトランザクションを開始し、そのオブジェクトに削除する必要のある BLOB 参照がアタッチされている場合、問題が発生します。ブロブを削除するだけでは、トランザクションは失敗する可能性がありますが、ブロブストアは独立して動作するため、ブロブはなくなります (これはトランザクションの考え方に反します)。

今、私たちは問題を解決できる文書化された API(?) のないインコンテキスト キャッシュを持つ、このクールな新しい NDB を手に入れました。

ツールチェスト:

  • 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)
    

タスク: トランザクション中に削除するブロブキーをコンテキスト オブジェクトにアタッチし、トランザクション後に削除します。

更新: call_on_commit() はデータベース操作 (blobstore.delete を含む可能性がありますが、試したことはありません) を許可せず、BadRequestError: Cannot start a new operation in a finished transaction をスローします。そのため、唯一の解決策は本当にタスクキューである可能性があります。

更新: call_on_commit() で登録された関数から @ndb.non_transactional デコレータを使用して関数を呼び出すことができます。そのため、コミットが成功したときに BLOB を削除しようとする可能性があり、孤立につながる例外がないことを願っています。

質問: インコンテキスト キャッシュを安全に使用するにはどうすればよいですか? ブロブ削除の問題をどのように解決しましたか?

4

2 に答える 2

0

BLOB を含むエンティティ グループを孤立せずに削除する方法の 1 つは、トランザクションを使用せずに繰り返し可能なフォールト トレラントな削除操作 (べき等操作) を使用することです。

  1. エンティティ/祖先に削除済みのマークを付けて配置します (誰も使用できないようにすることが重要です)
  2. 葉から親へのトランザクションなしで削除
  3. エラーが発生するたびに、中止します
  4. ユーザー (削除されたアイテムが表示される) またはシステム (タスクキュー) は、後で削除を再試行できます。
  5. 削除は、冪等であるために、既に削除された参照をスキップできる必要があります

誰でもそのアプローチで問題を見ることができますか?

于 2013-07-20T12:50:29.640 に答える