Dependency injection 依赖项注入,监控组件的stuartsierra/component中的循环依赖项

Dependency injection 依赖项注入,监控组件的stuartsierra/component中的循环依赖项,dependency-injection,clojure,health-monitoring,Dependency Injection,Clojure,Health Monitoring,我的组件存在循环依赖性问题 我有: webServer组件 一种Healthcheck组件,定期在系统中查找实现Healthcheck协议的组件。这是监测的一部分 数据库、作业队列连接等组件,实现healthcheck协议 WebServer还实现了healthcheck协议 我有一个函数,给定一个系统,它返回compojure路由,允许查询存储在healthcheck组件中的最后一个healthcheck状态 因此,我现在在这个函数中有一个循环依赖项和一个解决方法,就是将系统作为一个var

我的组件存在循环依赖性问题

我有:

  • webServer
    组件
  • 一种
    Healthcheck
    组件,定期在系统中查找实现
    Healthcheck
    协议的组件。这是监测的一部分
  • 数据库、作业队列连接等组件,实现
    healthcheck
    协议
WebServer
还实现了
healthcheck
协议

我有一个函数,给定一个系统,它返回compojure路由,允许查询存储在healthcheck组件中的最后一个healthcheck状态

因此,我现在在这个函数中有一个循环依赖项和一个解决方法,就是将系统作为一个
var
,并在需要时取消对它的引用,而不是将它作为一个值

但这是不方便的,这意味着在启动期间,检查会在一段时间内报告一个不正确的值


有没有办法在组件中处理这种生命周期?或者这里是否存在设计缺陷?

与通常的循环依赖一样,您可以通过将一些麻烦的功能提取到一个或多个附加组件中以打破循环来解决此问题。一种方法是将“webserver”组件重命名为“apphandler”或其他名称,并使其包括除基于监视的路由之外的所有路由。它实际上不应该启动Web服务器本身,而应该提供一个可以用来启动服务器的环处理程序函数

在这一点上,添加一个依赖于应用程序处理程序的“监控”组件当然很容易,而且它可以生成整个系统的运行状况(除了Web服务器本身,我们还没有了解它)

最后,一个新的“Web服务器”组件可以采用应用程序处理程序提供的路由,并启动一个Web服务器,该服务器将这些路由与一个附加的
/monitoring
处理程序或其他任何东西组合在一起,该处理程序会询问监视组件情况如何。如果愿意,您可以在这里添加关于Web服务器本身的状态,尽管实际上,如果Web服务器不健康,您在许多情况下将无法通过Web服务器本身对其说任何有用的话

总结组件依赖关系图的图表:

显然,堆栈溢出不支持嵌入SVG文件,所以我不得不在外部托管它


您可以采取完全不同的方法,让监控组件完全没有依赖项,而是基于插件/注册。每个系统都依赖于监控系统,作为启动的一部分,它将通过提供一些回调来注册自己,以回答“我有多健康?”


在某些方面,我认为这与组件的精神背道而驰,因为您正在向依赖关系图添加隐式后向边,但我认为这是一种合理的方法。这更多地证明了“计算机科学中的所有问题都可以通过另一种间接方式来解决”这句古老的格言。在C和类似的语言中,这通常意味着另一个级别的指针;在函数式语言中,它通常意味着用函数替换一个值。

“它实际上不应该启动Web服务器本身,而应该提供一个可以用来启动服务器的环处理程序函数。”。我不知道那会是什么样子?我所描述的更像是(我不知道组件系统映射的实际语法,所以很明显这是一个草图)。在您的草图中,
监控
健康检查
?我尝试了类似的方法,但组件似乎想要映射而不是函数(在自述文件中搜索“将像这样启动”),只有在注入依赖项时。旁注:“在函数语言中,它通常意味着用函数替换一个值。”从来没有想过这些,很有趣!