Clojure:需要架构建议

Clojure:需要架构建议,clojure,publish-subscribe,Clojure,Publish Subscribe,我正在编写一个小clojure发布/订阅界面。这是非常简单的,实际上只有两种方法可以使用:pub和sub-listen。sub-listen接受一个字符串(子名称),do-pub接受两个字符串(子名称和值) 我在clojure还是个新手,在想出一个可行的方法时遇到了一些困难。我的第一个想法(事实上是我的第一个实现)是使用一个单独的代理来保存哈希: { subname (promise1 promise2 etc) } 当一个线程想要将它的conj的一个promise对象分到与它想要的子对象相关

我正在编写一个小clojure发布/订阅界面。这是非常简单的,实际上只有两种方法可以使用:pub和sub-listen。sub-listen接受一个字符串(子名称),do-pub接受两个字符串(子名称和值)

我在clojure还是个新手,在想出一个可行的方法时遇到了一些困难。我的第一个想法(事实上是我的第一个实现)是使用一个单独的代理来保存哈希:

{ subname (promise1 promise2 etc) }
当一个线程想要将它的conj的一个promise对象分到与它想要的子对象相关联的列表时,然后立即尝试取消引用该promise(因此阻塞)

当pub发生时,它会遍历sub列表中的每一项,并将值传递给该项(承诺)。然后,它从映射中分解该子名称并将其返回给代理

通过这种方式,我得到了一个简单的pub-sub实现。然而,当有人在一段时间内没有收到酒吧,然后由于超时而被杀死时,问题就出现了。在这种情况下,代理中会有一个不需要的毫无价值的承诺,而且如果sub从未发布,这将是内存泄漏的来源


有人对如何解决这个问题有什么想法吗?或者,如果有更好的方法来完成我想做的事情(我试图避免使用任何外部预处理的pubsub库,这是一个宠物项目而不是工作项目)?

您可以这样做:

  • 创建一个
    atom
  • publish
    函数将通过传递给函数的值更新原子值
  • 订户可以在atom上使用
    add watch
    ,以便在atom值发生变化时(即由于调用
    publish
    功能)收到通知
  • 使用
    remove watch
    删除订阅

这样,您将拥有一个非常基本的酒吧子系统。

我已将Ankur的答案标记为解决方案,但我想对其进行一点扩展。我最后做的是拥有一个中心atom,所有客户端线程都对它执行
addwatch
。发布完成后,原子的值将更改为一个向量,其中包含子元素的名称和发布的值

客户端传递给
addwatch
的函数是一个部分函数,如下所示

(partial (fn [prom sub key ref _old new] ...) sub prom)
其中prom是先前生成的承诺。然后,客户在等待该承诺时阻止。部分功能检查
new
中的sub是否与
sub
相同,如果相同,则移除手表并使用
new
中的值兑现承诺