2017-10-14 79 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所有其他工作 –