从另一个应用程序使用 GenServer
Using GenServer from another application
我现在正在努力在我的伞式应用程序的另一个应用程序中使用 GenServer。
结构:
应用程序:
- project_a
- project_b
Project_a 和 project_b 都是 --sup
应用程序,我想在 project_b 中使用来自 project_a 的 GenServer。我已将该项目包含在我的 deps.exs 文件中,但我不知道下一步该做什么...
如果我打开观察器,我会在菜单中看到这两个应用程序,但我不断收到错误消息,因为 project_b 无法使用 project_a。
有谁知道我忘记了什么?
我忘记在 project_b
的 mix.exs
文件中添加 project_a
。
添加as dep是不行的,还必须在de def application
部分添加。
虽然您对自己问题的回答是正确的,但我可以根据经验告诉您,在另一个应用程序中为您的服务编写适配器是一种很好的做法,旨在将两个应用程序更松散地耦合在一起并避免循环引用.
这是什么意思?获取您要向其发送消息的 GenServer 的 public API 部分,并将其移动到另一个应用程序中的另一个模块。您会发现这与为 HTTP API 编写外观非常相似。 GenServer 的 public API 部分实际上是来自调用进程的 运行 ,即使它在 GenServer 的模块中,所以将它移动到另一个模块就可以了。
请原谅以下代码中的任何语法问题等,因为我正在把它从脑海中拉出来。
改成这样:
defmodule App1.Calculator do
use GenServer
def add( num1, num2 ), do: GenServer.call( App1.Caclculator, {:add, num1, num2})
def handle_call({:add, num1, num2}, _from, state) do
{:reply, {:ok, num1+num2}, state}
end
end
收件人:
defmodule App1.Calculator do
use GenServer
def handle_call({:add, num1, num2}, _from, state) do
{:reply, {:ok, num1+num2}, state}
end
end
defmodule Service.Calculator do
def add(num1, num2), do: GenServer.call(process_name, {:add, num1, num2})
# Just an example of how you might have named your node and calculator process
def process_name, do: {:calculator, :"app1@127.0.0.1"}
end
其中 Service.Caclulator
在名为 Service
的第三个应用程序中,App1
和 App2
可以依赖该应用程序而无需创建循环引用。
为什么必须创建循环引用?一旦您使用 cast
从 App1
到 App2
异步执行操作,那么 App2
将不得不将包含结果的消息发送到 App1
,并且没有在第 3 个 Service
应用程序中,您将创建 App1
和 App2
的循环引用。更不用说当您开始发布两个节点(一个用于每个应用程序)时,无需包含所有其他应用程序的编译代码只是为了获得服务的适配器。
我现在正在努力在我的伞式应用程序的另一个应用程序中使用 GenServer。
结构:
应用程序:
- project_a
- project_b
Project_a 和 project_b 都是 --sup
应用程序,我想在 project_b 中使用来自 project_a 的 GenServer。我已将该项目包含在我的 deps.exs 文件中,但我不知道下一步该做什么...
如果我打开观察器,我会在菜单中看到这两个应用程序,但我不断收到错误消息,因为 project_b 无法使用 project_a。
有谁知道我忘记了什么?
我忘记在 project_b
的 mix.exs
文件中添加 project_a
。
添加as dep是不行的,还必须在de def application
部分添加。
虽然您对自己问题的回答是正确的,但我可以根据经验告诉您,在另一个应用程序中为您的服务编写适配器是一种很好的做法,旨在将两个应用程序更松散地耦合在一起并避免循环引用.
这是什么意思?获取您要向其发送消息的 GenServer 的 public API 部分,并将其移动到另一个应用程序中的另一个模块。您会发现这与为 HTTP API 编写外观非常相似。 GenServer 的 public API 部分实际上是来自调用进程的 运行 ,即使它在 GenServer 的模块中,所以将它移动到另一个模块就可以了。
请原谅以下代码中的任何语法问题等,因为我正在把它从脑海中拉出来。
改成这样:
defmodule App1.Calculator do
use GenServer
def add( num1, num2 ), do: GenServer.call( App1.Caclculator, {:add, num1, num2})
def handle_call({:add, num1, num2}, _from, state) do
{:reply, {:ok, num1+num2}, state}
end
end
收件人:
defmodule App1.Calculator do
use GenServer
def handle_call({:add, num1, num2}, _from, state) do
{:reply, {:ok, num1+num2}, state}
end
end
defmodule Service.Calculator do
def add(num1, num2), do: GenServer.call(process_name, {:add, num1, num2})
# Just an example of how you might have named your node and calculator process
def process_name, do: {:calculator, :"app1@127.0.0.1"}
end
其中 Service.Caclulator
在名为 Service
的第三个应用程序中,App1
和 App2
可以依赖该应用程序而无需创建循环引用。
为什么必须创建循环引用?一旦您使用 cast
从 App1
到 App2
异步执行操作,那么 App2
将不得不将包含结果的消息发送到 App1
,并且没有在第 3 个 Service
应用程序中,您将创建 App1
和 App2
的循环引用。更不用说当您开始发布两个节点(一个用于每个应用程序)时,无需包含所有其他应用程序的编译代码只是为了获得服务的适配器。