2017-05-05 8 views
0

私は、特定のパラメータを持つエンティティが存在するかどうかを調べるクエリを最初に使用するエンドポイントメソッドを持っています。それが存在する場合、私は変数にカウンターを増やすことをお勧めします:このエンドポイントで2つのエンティティがデータストアに書き込まれますか?

Report report = ofy().load().type(Report.class) 
    .filter("userID", userID) 
    .filter("state", state).first().now(); 

if (report == null) { 
    //write new entity to datastore with userID and state 
} else { 
    //increase counter in entity +1 
    report.setCount(report.count+1) 
    //save entity to datastore 
} 

私の質問は、誰かが非常に急速に同じのparamsで上記のエンドポイントを実行するためのボタンを、クリックした場合に何が何が起こるか、ですか? 2つの同一のレポートエンティティがデータストアに書き込まれますか?私はただ一つが書かれていることを確認したい。

答えて

1

このコード自体は安全ではなく、複数のレポートを作成できる競合状態があります。

これを安全にするには、トランザクションでコードを実行する必要があります。これは、祖先クエリを持つ必要があることを意味します(または、単純な主キーの参照に変換する必要があります)。 1つの選択肢は、報告書にユーザの@Parentを与えることです。

+0

上記のコードで書いたことをすれば、誰かが私のメソッドを短時間で非常に迅速に実行したらどうなりますか?電話はちょうどキューに入れられますか?応答がクライアントに返される前にこれが起こるので、いくらか遅延がありますか? – BlueBoy

+0

データストアは楽観的同時実行モデルを使用します。つまり、低レベルAPIは1トランザクションを除くすべてのトランザクションに対して 'ConcurrentModificationException'をスローします。 Objectifyはこれを再試行の手がかりにします。したがって、単一のエンティティグループ(通常は1秒あたり1〜5)の最大レートでコミットされたトランザクションを取得し、他のすべてのリクエストはスピン/ブロック待機します。それが長く続くと、要求はタイムアウトになります。あなたは単一のエンティティグループ上で多くの競合を望んでいません。 – stickfigure

関連する問題