我希望有一个类似于频道的消防水管,可以编写可由当前连接的客户端检索的数据。我想要一个看起来像这样的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)
我提出的要求是:
dupXXX
和closeXXX
,但是关闭并不会终止所有内容。我认为没有一个已经写过的类似Chan的模块,写起来似乎并不容易。以下是我的问题:
编辑:这实际上是一个非常有用的结构。以下是我将要使用的内容:碰巧我的生产系统中有几条消息总线。我希望能够动态地将远程客户端连接到此总线,以便在传输过程中实时检查某些消息。这对于调试和报告很有用。
答案 0 :(得分:2)
您可能需要某种IORef来保存数据和客户列表。一种可能的解决方案是保留客户端处理程序列表(客户端插入的[a-> IO()]函数以“订阅”)。这具有以下优点:一旦广播完成就不需要将数据本身存储在任何地方,因此遵守“有界存储器”要求。您的subscribe
和broadcast
函数编写起来非常简单,它们只需向列表中添加一个函数,并遍历调用每个函数的列表。缺点是一旦广播完成,数据就会消失......
另一种可能性是使用IORef来存储实际数据。在这种方法中,您将保留[a]
的列表,并在广播时添加到列表中。可以使用push发送数据(在这种情况下,您将需要一个单独的[IO()]函数列表,无论如何对应于客户端),或拉动,在这种情况下,您需要使用序列标记每个a
数字或时间戳(客户端将用于确定什么是新的)。我会尽可能避免拉扯案例(通常涉及民意调查,这是邪恶的)。
老实说,如果你是一个客户来找我这个规格,我会更加努力地确定规格是否真的是你想要的......如果不了解更多关于这个问题,我不能说当然,但几乎听起来你希望这些客户端是远程的,在这种情况下可能需要tcp / ip服务器/客户端模型。如果是这种情况,请忽略我上面提到的所有内容,你可能想要添加一个数据库,并且需要建立通信协议。
或者您可能需要在中间客户端运行另一个进程,但在同一台计算机上。对于这种情况,链接库或Microsoft COM对象(包裹在数据库中,甚至只包含几个文件)可能符合要求。
我怀疑所有的贬低是因为规格不是那么明确,因为我给你的任何这些非常不同的答案都可能满足要求。 (我不是其中一位贬低者)。