2

Voteしばらく使用してきた db モデルがあり、最近Score、投票に基づいてエンティティの累積スコアを表す ndb モデルを追加しました。Scoreすべてを同じエンティティ グループに含める必要があるため (同じトランザクションで更新できるようにするため)、現在は投票の親です。Vote両方を更新するトランザクションを機能させようとしましたScoreが、一貫して失敗します。サンプルコードは次のとおりです。

    def transaction():
        score = self.key_score.get()
        vote = db.get(self.key_vote)

        # do stuff

        score.put()
        vote.put()
    db.run_in_transaction(transaction)

私が知る限り(開発サーバーのみ)、これは常に4回再試行します:

WARNING:root:Transaction collision. Retrying...
WARNING:root:Transaction collision. Retrying...
WARNING:root:Transaction collision. Retrying...
WARNING:root:Transaction collision. Retrying...
ERROR

次に、「TransactionFailedError: トランザクションをコミットできませんでした。もう一度お試しください。」というメッセージが表示されます。

これを修正するためにいくつかのことを試しました:

  1. get と put の順序を変更する - 理解できないエンティティ グループのロックの問題があるのではないかと思いましたが、get と put の順序を変更しても動作は変わりませんでした。

  2. 非同期プット。これは実際に私が始めたものです-dbとndbモデルを同時に配置する唯一の方法です(これは本質的に、複数のキーを舞台裏で配置することだと思います)。同じ結果です。

    score_future = score.put_async()
    vote_future = db.put_async(vote)
    score_future.get_result()
    vote_future.get_result()
    
  3. に置き換えdb.run_in_transactionますndb.transaction。これにより、「AttributeError: 'Key' object has no attribute 'reference'」がスローされますdb.get。ここで何が起こっているのかわかりません - 舞台裏のコードがdb.Key期待どおりの場所に到達しているようですndb.Key

興味深いことに、関係を削除すると、上記と同じコードを実行できますparent。つまり、エンティティが同じエンティティ グループに属していないということです。

では、db モデルと ndb モデルの両方を同じエンティティ グループに含めることは可能ですか? おそらく、db モデルを ndb として取得する簡単な方法、またはその逆の方法はありますか?

4

1 に答える 1

5

DB で作成されたか NDB で作成されたかに関係なく、すべてのエンティティはデータストアには同じように見えます。ここでの問題は、API 呼び出しで 2 つを混在させようとしていることです。db は、ndb モデル インスタンスが渡されたときに何をすべきかわかりません。

Vote の db モデルと同じ NDB モデルを作成する必要があります。または、Vote を NDB モデルに移行し、両方のエンティティ タイプのトランザクションが必要なコードでそれを使用する必要があります。

于 2012-11-09T20:56:00.247 に答える