2

レース条件

私の Meteor アプリケーションでは、特定の条件でいくつかの新しいデータを挿入するobserve内に を作成しました。publishポイントは、サブスクリプションが重複している場合があり、競合状態により、挿入されたデータが重複することです。「シングルトンオブザーバー」を持つことができない場合:

  • 競合状態とデータベースへの挿入データの重複を回避するにはどうすればよいですか?

例:

Meteor.publish("fortuneUpdate", function () {
  var selector = {user: this.userId, seen:false};

  DailyFortunes.find(selector).observe({
    removed: function(doc, beforeIndex){
      if(DailyFortunes.find(selector).count()<1)
        createDailyFortune(this.userId);
    }
  });

}

この質問は、「cursor.observe の仕組みと複数のインスタンスの実行を回避する方法」から移動されました。

4

2 に答える 2

2

これは奇妙なパターンです。サンプルコードを共有できますか?

observe一般的に、私はメソッドにミューテーションが見られるか、サーバーに内部を設定することを期待してMeteor.startup()います。(複数のサーバー プロセスを実行している場合、後者は注意が必要ですが、マルチ プロセス体制では他の多くのことも同様です。後でより良いパターンが得られるでしょう。)

任意の JS である可能性があるため、発行関数はサブスクライブするクライアントごとに 1 回実行する必要があります。this.userId新しいサブスクリプションをログに記録したり、クライアントごとのサーバー状態を設定したり、またはランダムなソースに基づいて動作を変更したりできます。たとえば、DB コレクションからランダムに選択された 10 個のドキュメントをサブスクライブした各クライアントに返すサブスクリプションを考えてみましょう!

したがって、多数のクライアントが同じデータ セットにサブスクライブしている場合を最適化する場所は、DB クエリ レイヤーです。1,000 のクライアントが同じ DB クエリにサブスクライブしている場合、その基礎となるクエリを 1 回だけ実行します。

于 2012-11-09T16:44:53.900 に答える
2

Tom によると、今のところ、同じ引数を持つ subscribe の呼び出しを確実に共有することはできません。したがって、オブザーバー内で冗長データが作成されるという私と同じ問題が発生している場合は、回避策として次のことをお勧めします。

  1. 繰り返しのデータ作成を防ぐ堅牢な インデックスを作成します。複合キーは、おそらくここで必要なものです。
  2. 競合状態を無視して、オブザーバー内で重複キー エラー例外を処理します。

:

Collection.find(selector).observe({
  removed: function(document){
      try {
        // Workaround to avoid race conditions > https://stackoverflow.com/q/13095647/599991
        createNewDocument();
      } catch (e) {
        // XXX string parsing sucks, maybe
        // https://jira.mongodb.org/browse/SERVER-3069 will get fixed one day
        if (e.name !== 'MongoError') throw e;
          var match = e.err.match(/^E11000 duplicate key error index: ([^ ]+)/);
        if (!match) throw e;
        //if match, just do nothing.
      }
    self.flush();
  }
});
于 2012-11-08T21:06:15.417 に答える