2017-10-14 77 views
3

該設置類似於this。 一個代理(dataSource)正在生成數據,而單個代理(dataProcessor)正在處理這些數據。生成的數據比dataProcessor可以處理的數據多得多,我不想處理所有消息,只處理最新的數據。郵箱處理器,最新信息

喬恩哈羅普在那裏提出的一種可能的解決方案是「當一個人到達並丟棄除最近的所有消息之外,貪婪地吃掉收件箱中的所有消息」。 另一種方法是不聽所有的消息,而是爲dataProcessorPostAndReplydataSource獲取最新的一條數據。

這些方法的優缺點是什麼?

回答

3

這是一個有趣的問題,並且存在很多可能的觀點。我認爲,最顯着的方面是,選擇會影響你如何在這兩個組件之間的接口設計的API:

  1. 在「消費」的辦法,生產者有一個非常簡單的API,其中它會觸發一些事件每當產生一個價值,你的消費者就會訂閱它。這意味着您可以讓其他訂閱者傾聽來自制作人的更新,並從這個問題中做出比您的消費者更多的東西。

  2. 在「調用最新」方法中,生產者可能需要寫入,以保持當前狀態並丟棄舊值。然後它將提供阻塞異步API以獲取最新值。儘管如此,它仍然可以爲其他消費者揭露事件。消費者將需要積極調查變化(在某種忙碌的環境中)。

  3. 您也可以在「Consume all」中擁有一個帶有事件的生產者,但隨後創建另一個組件來偵聽任何給定的事件,保留最新值並通過阻止異步調用將其提供給任何其他客戶端。

這裏一些優點/缺點我能想到的:

  • 在(1)的生產是非常簡單;消費者很難寫
  • (2)生產者需要做更多的工作,但消費者很簡單
  • 在(3)中,您要添加另一個層,但是要以相當可重用的方式。

我可能會去與(2)(如果我只需要這一個數據源)或與(3)檢查後,它不會影響性能。

至於(3)中,我在想什麼會是這個樣子的素描:

type KeepLastMessage<'T> = 
    | Update of 'T 
    | Get of AsyncReplyChannel<'T> 

type KeepLast<'T>(initial:'T, event:IObservable<'T>) = 
    let agent = MailboxProcessor.Start(fun inbox -> 
    let rec loop last = async { 
     let! msg = inbox.Receive() 
     match msg with 
     | Update last -> return! loop last 
     | Get ch -> ch.Reply(last); return! loop last } 
    loop initial) 
    member x.AsyncGet() = agent.PostAndAsyncReply(Get) 
+0

非常感謝您Petricek博士,這和F#comunity所有其他工作 –