3

TL;博士

如果 OTP 应用程序 A 在应用程序 B 中调用全局注册的 gen_server,并且我不想在不运行它的节点上安装所有应用程序 B,我该如何处理 gen_servers 客户端代码?

背景(略微简化)

我有一个使用分布式 erlang 的系统,2 个具有不同目的的节点,运行大部分不同的代码。到目前为止,我一直在使用手工制作的 Makefile 并在两个节点上安装了所有软件。一些代码作为 OTP 应用程序与主管一起运行,但它没有系统地完成,因此并非所有模块都列在适当监督树的一部分的任何应用程序文件中。

在每个节点上运行的代码的依赖关系非常不同,我想将其划分为 OTP 应用程序(每个节点一个),以构建版本并分别安装它们。我希望这能让我放弃手工制作的 Makefile 并切换到 rebar3。

一个节点在所有 erlang 中运行一个中央服务器,它具有与另一个节点无关的依赖项(牛仔)。另一个节点运行一个使用服务器的客户端程序,但也使用服务器节点不需要的不同端口程序和 gui 库。

问题

客户端与服务器交互的方式是对全局注册的 gen_server 的客户端 API 进行常规函数调用。即在服务器节点上运行的gen_server,在同一个模块中具有它的客户端功能。这意味着这个 gen_servers 光束文件需要存在于两个节点中,但它应该只是其中一个应用程序中监督树的一部分。

此 gen_server 中的服务器端代码使用仅在服务器节点中需要的其他模块,因此 gen_server 的测试代码也依赖于这些其他模块。(我意识到这可以通过在测试中进行适当的模拟来解决。)

我考虑了哪些解决方案?

将其放入库应用程序中

我可以将 gen_servers 代码放在其他两个都依赖的库应用程序中。出于几个原因,这会很奇怪。

  • gen_server 模块不会与它所依赖的其他模块属于同一应用程序的一部分(并且与代码中的实际依赖关系相比,应用程序级别的依赖关系将被颠倒)。
  • 测试代码要么需要保留在服务器应用程序中(与它测试的代码不同的应用程序),要么重新工作以不依赖于周围的模块(这很好但很耗时)。

在两个版本中包含服务器应用程序

我可以在两个节点中都包含服务器应用程序,并让主管代码检查它是否应该基于 init-arguments 或节点名称实际启动任何内容。但这会破坏我正在尝试做的事情的目的。

在两个应用程序中包含 gen_server 模块

我也可以使用符号链接或其他东西在客户端应用程序中包含 gen_server 模块。我想它会起作用,但感觉很脏。

将 gen_server 模块拆分为客户端模块和服务器模块

然后客户端模块可以放在客户端应用程序中(或者如果该服务器的某些部分也使用它,则放在一个库中)。它会大大偏离 gen_severs 通常的编写方式。

4

0 回答 0