2012-11-08 101 views
2

賽condiditions

在我的流星申請,我一個publish內提出observe,在一定的條件下插入一些新的數據。問題是,有時我們有重複訂閱,競爭條件導致我們重複插入的數據。 如果是not possible to have "singleton observers"如何避免cursor.observe上的競爭條件?

  • 我們如何才能避免對數據庫競爭條件和重複插入的數據?

例子:

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); 
    } 
    }); 

} 

這個問題已經被從How cursor.observe works and how to avoid multiple instances running?

+1

請注意,我沒有說過不可能做單身觀察者,只是他們的某一類會在以後的版本中爲你自動完成(我相信)。 –

回答

2

According to Tom移動,這是不可能的,現在,以確保調用訂閱具有相同參數是共享的。 所以,如果你有同樣的問題,我觀察內部創建冗餘數據,我建議你,作爲解決方法,以:

  1. 創建穩健indexes防止repeted數據生成。 Compound Keys很可能是你在這裏需要的。
  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(); 
    } 
}); 
2

這是一個奇數模式。你能分享一些示例代碼嗎?

通常我會希望在方法中看到突變,或者在服務器上設置Meteor.startup()內部的observe。 (後者是棘手的,如果你運行多個服務器進程,但在多進程機制中還有很多其他的東西,我們會有更好的模式。)

因爲它可以是任意的JS,發佈功能必須爲每個訂閱客戶端運行一次。它可能會記錄新的訂閱,設置每個客戶端的服務器狀態,或者根據this.userId甚至隨機源來改變其行爲。例如,考慮從數據庫集合向每個訂閱的客戶端返回10個隨機選擇的文檔的訂閱!

因此,優化訂閱相同數據集的許多客戶端大小寫的地方是在數據庫查詢層:如果有一千個客戶端訂閱了相同的數據庫查詢,我們只運行一次底層查詢。

+0

我加了一個例子,現在可能更容易理解。 我不認爲'Meteor.startup()'可以處理基於用戶連接的數據庫修改。它可以? – zVictor