消防水带像通道

时间:2013-12-24 15:02:55

标签: haskell data-structures

我希望有一个类似于频道的消防水管,可以编写可由当前连接的客户端检索的数据。我想要一个看起来像这样的API:

-- I chose IO to illustrate, but any suitable monad such as STM would be fine
newFirehose :: SomeConfiguration -> IO (Firehose a)
ghReader :: Firehose a -> IO (FirehoseReader a)
closeReader :: FirehoseReader -> IO ()
broadcast :: Firehose a -> a -> IO ()
-- returns nothing for closed readers
receive :: FirehoseReader a -> IO (Maybe a)

我提出的要求是:

  • 应该可以随意添加和删除客户端,这意味着dupXXXcloseXXX,但是关闭并不会终止所有内容。
  • 可以使用只读和只写类型的接口。
  • 它应该使用有限的内存量。
  • 客户如果没有从消防水带读取,或者速度慢,则不得阻止其他客户。
  • 丢弃值是可以接受的。
  • 如果没有性能问题,所有客户端都应收到相同的数据。

我认为没有一个已经写过的类似Chan的模块,写起来似乎并不容易。以下是我的问题:

  • 那里有什么东西可用吗?
  • 我错过了一个关键要求吗?
  • 有人可以分享关于如何编写这样一个结构的指针或想法吗?

编辑:这实际上是一个非常有用的结构。以下是我将要使用的内容:碰巧我的生产系统中有几条消息总线。我希望能够动态地将远程客户端连接到此总线,以便在传输过程中实时检查某些消息。这对于调试和报告很有用。

1 个答案:

答案 0 :(得分:2)

您可能需要某种IORef来保存数据和客户列表。一种可能的解决方案是保留客户端处理程序列表(客户端插入的[a-> IO()]函数以“订阅”)。这具有以下优点:一旦广播完成就不需要将数据本身存储在任何地方,因此遵守“有界存储器”要求。您的subscribebroadcast函数编写起来非常简单,它们只需向列表中添加一个函数,并遍历调用每个函数的列表。缺点是一旦广播完成,数据就会消失......

另一种可能性是使用IORef来存储实际数据。在这种方法中,您将保留[a]的列表,并在广播时添加到列表中。可以使用push发送数据(在这种情况下,您将需要一个单独的[IO()]函数列表,无论如何对应于客户端),或拉动,在这种情况下,您需要使用序列标记每个a数字或时间戳(客户端将用于确定什么是新的)。我会尽可能避免拉扯案例(通常涉及民意调查,这是邪恶的)。

老实说,如果你是一个客户来找我这个规格,我会更加努力地确定规格是否真的是你想要的......如果不了解更多关于这个问题,我不能说当然,但几乎听起来你希望这些客户端是远程的,在这种情况下可能需要tcp / ip服务器/客户端模型。如果是这种情况,请忽略我上面提到的所有内容,你可能想要添加一个数据库,并且需要建立通信协议。

或者您可能需要在中间客户端运行另一个进程,但在同一台计算机上。对于这种情况,链接库或Microsoft COM对象(包裹在数据库中,甚至只包含几个文件)可能符合要求。

我怀疑所有的贬低是因为规格不是那么明确,因为我给你的任何这些非常不同的答案都可能满足要求。 (我不是其中一位贬低者)。