2

比赛条件

在我的 Meteor 应用程序中,我做了一个observewithin a 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

根据 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 回答
2

这是一个奇怪的模式。你能分享一些示例代码吗?

一般来说,我要么希望看到方法中的突变,要么在服务器上设置一个observe内部。Meteor.startup()(如果您正在运行多个服务器进程,后者会很棘手,但多进程机制中的许多其他事情也是如此。我们将有一个更好的模式。)

因为它可以是任意 JS,所以发布函数必须为每个订阅客户端运行一次。它可能会记录新的订阅,设置每个客户端服务器状态,或者根据this.userId甚至是随机源改变其行为。例如,考虑一个从数据库集合中随机选择的 10 个文档返回给每个订阅客户端的订阅!

因此,优化多个客户端订阅相同数据集的情况的地方是数据库查询层:如果有一千个客户端订阅了同一个数据库查询,我们将只运行该底层查询一次。

于 2012-11-09T16:44:53.900 回答