命名Elixir GenServer进程与实现它们的模块不同

时间:2016-02-12 16:02:30

标签: elixir otp gen-server

我有一个名为Tornado的模块,它实现了GenServer,我试图将它作为一个名称与模块名称不同的进程产生。 根据{{​​3}},可以通过给出一个原子作为参数来注册GenServer进程

children = [
  worker(Tornado, [[], [name: :tornado_server]])
]

但是当我尝试调用函数时,我收到一个错误:

iex(2)> :tornado_server.send_requests 
** (UndefinedFunctionError) undefined function :tornado_server.send_requests/1 (module :tornado_server is not available)

我还尝试将:tornado_server更改为TornadoServer

** (UndefinedFunctionError) undefined function     TornadoServer.send_requests/1 (module TornadoServer is not available)

修改

这是Tornado模块

defmodule Tornado do
  use GenServer

  # Public API
  def start_link(state,  opts \\ []) do
    GenServer.start_link __MODULE__, state, opts
  end

  def send_requests(requests) do
    GenServer.cast(self, {:send_requests, requests})
  end

  def get_responses do
    GenServer.call(self, :get_responses )
  end

  # GenServer API
  def init(state) do
    # creaza 10 Ci
    { :ok, state }
  end

  def handle_cast({:send_requests, requests}, state) do
    state = state ++ [{requests, "127.0.0.1\n"}]
    {:noreply, state }
  end

  def handle_call(:get_responses, _from, state) do
    {:reply, state, state}
  end
end

以下是启动它的主管:

defmodule TornadoSupervisor do
  use Supervisor

  def start_link do
    Supervisor.start_link(__MODULE__,[])
  end

  def init([]) do
    children = [
      worker(Tornado, [[], [name: :tornado_server]])
    ]

    supervise(children, strategy: :one_for_one)
  end
end

基本上我想这样称呼它:

 > TornadoSupervisor.start_link
 > TornadoServer.send_requests some_requests_array
 > TornadoServer.get_responses

稍后编辑 显然它是有效的,如果我这样做

 > GenServer.cast(TornadoServer, {:send_requests,requests})
 > GenServer.call(TornadoServer, :get_responses )

但我发现这种语法太冗长了。

1 个答案:

答案 0 :(得分:3)

使用:tornado_server.send_requests调用您的函数将查找不太可能的erlang模块tornado_server

您仍需要调用模块上的函数,使用该名称代替pid,而不是模块名称。

如果没有看到您的模块,很难进一步建议。我建议您阅读http://elixir-lang.org/getting-started/mix-otp/genserver.html然后http://elixir-lang.org/getting-started/mix-otp/supervisor-and-application.html来查看命名流程的工作原理。

修改

GenServer.cast/call期望pid(或注册名称)作为第一个参数。您正在使用的pid(self的结果)是调用者,而不是正在运行的GenServer。

您应该存储pid并执行以下操作:

{:ok, pid} = Tornado.start_link()
Tornado.send_requests(pid, some_requests_array)
Tornado.get_responses(pid)

或者您应该替换您的实现以使用提供的名称:

  def send_requests(requests) do
    GenServer.cast(:tornado_server, {:send_requests, requests})
  end

  def get_responses do
    GenServer.call(:tornado_server, :get_responses )
  end

不清楚为什么你不想使用模块名称。对于GenSever来说,这是一个非常常见的约定,你只需要1个。