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: トランザクションをコミットできませんでした。もう一度お試しください。」というメッセージが表示されます。
これを修正するためにいくつかのことを試しました:
get と put の順序を変更する - 理解できないエンティティ グループのロックの問題があるのではないかと思いましたが、get と put の順序を変更しても動作は変わりませんでした。
非同期プット。これは実際に私が始めたものです-dbとndbモデルを同時に配置する唯一の方法です(これは本質的に、複数のキーを舞台裏で配置することだと思います)。同じ結果です。
score_future = score.put_async() vote_future = db.put_async(vote) score_future.get_result() vote_future.get_result()
に置き換え
db.run_in_transaction
ますndb.transaction
。これにより、「AttributeError: 'Key' object has no attribute 'reference'」がスローされますdb.get
。ここで何が起こっているのかわかりません - 舞台裏のコードがdb.Key
期待どおりの場所に到達しているようですndb.Key
。
興味深いことに、関係を削除すると、上記と同じコードを実行できますparent
。つまり、エンティティが同じエンティティ グループに属していないということです。
では、db モデルと ndb モデルの両方を同じエンティティ グループに含めることは可能ですか? おそらく、db モデルを ndb として取得する簡単な方法、またはその逆の方法はありますか?