Function 如何从Elixir GenServer处理程序中调用其他函数?

Function 如何从Elixir GenServer处理程序中调用其他函数?,function,erlang,elixir,otp,gen-server,Function,Erlang,Elixir,Otp,Gen Server,我有一个GenServer,它实现单个项目的功能,例如: def handle_call({:sync, id}, _from, state) do ## update data {:reply, data, sync} end 现在我想为多个ID处理此功能,例如: def handle_call({:sync_all, ids}, _from, state) do ## call sync for each id data = Enum.map(ids, fn

我有一个GenServer,它实现单个项目的功能,例如:

def handle_call({:sync, id}, _from, state) do
    ## update data
    {:reply, data, sync}
end
现在我想为多个ID处理此功能,例如:

def handle_call({:sync_all, ids}, _from, state) do
    ## call sync for each id
    data = Enum.map(ids, fn(id) ->
        GenServer.call(self(), {:sync, id})
    end)
    ## Further reduce down data to stats
    {:reply, data, sync}
end
但是,如果告诉我进程试图调用自己,那么这是无效的

我认为这一定是由于
调用的阻塞性质造成的。但是,如果在
sync\u all
版本中使用
cast
,也会发生同样的情况


所以我的问题是:如何从
handle\u call
handle\u cast
函数中调用其他
GenServer
任务?

在这种情况下,您通常会做的是将公共逻辑提取到一个单独的函数中:

def handle_call({:sync, id}, _from, state) do
  {data, state} = do_sync(id, state)
  {:reply, data, state}
end

def handle_call({:sync_all, ids}, _from, state) do
  {data, state} = Enum.map_reduce(ids, state, &do_sync/2)
  {:reply, data, state}
end

defp do_sync(id, state) do
  # do something
  {data, new_state}
end

在这种情况下,您通常会将通用逻辑提取到单独的函数:

def handle_call({:sync, id}, _from, state) do
  {data, state} = do_sync(id, state)
  {:reply, data, state}
end

def handle_call({:sync_all, ids}, _from, state) do
  {data, state} = Enum.map_reduce(ids, state, &do_sync/2)
  {:reply, data, state}
end

defp do_sync(id, state) do
  # do something
  {data, new_state}
end

对同一进程进行GenServer调用没有多大意义。一个进程一次处理一条消息。电话将等待应答。但是,在处理完当前消息之前,进程无法应答。您拥有的代码将在等待应答时超时,因为该进程永远不会处理当前消息,因此也永远不会处理随呼叫发送的消息


通常,可以使用强制转换和调用为其他进程定义一个接口,以便向该进程发送消息。您可以将实际数据转换建模为纯函数,然后根据需要从两个处理程序函数中的每一个调用这些函数。

对同一进程进行GenServer调用没有多大意义。一个进程一次处理一条消息。电话将等待应答。但是,在处理完当前消息之前,进程无法应答。您拥有的代码将在等待应答时超时,因为该进程永远不会处理当前消息,因此也永远不会处理随呼叫发送的消息


通常,可以使用强制转换和调用为其他进程定义一个接口,以便向该进程发送消息。您可以将实际的数据转换建模为纯函数,然后根据需要从两个处理程序函数中的每一个调用这些函数。

cast
应该在
handle\u call
中工作。你能发布代码的版本吗?该版本可以做到这一点,但对你不起作用。
cast
应该在
handle\u call
中起作用。你能发布代码的版本吗?它可以做到这一点,但不适合你?