Elixir GenServer 转换到其他节点的最佳方式

标签 elixir

我的 GenServer 中有以下功能:

def add_event(param1, param2) do
    Enum.each(:pg2.get_members("some_group"), fn pid -> GenServer.cast(pid, {:new_event, param1, param2}) end)
  end

  def handle_cast({:new_event, param1, param2}, state) do
    #do something
    {:noreply, state}
  end

我的想法是,每当调用 add_event 时,我想将此请求传递给其他节点中组的所有成员。我的问题是,直接在公共(public) api 内进行转换是个好主意还是在 handle_cast 回调内进行转换更好

最佳答案

Process 中进行调度(而不是在客户端 api 中),意味着这些优点和缺点:

优点:

  1. 真正的异步行为:由于分派(dispatch)是在服务器端的进程内进行的,因此您不会在分派(dispatch)完成后等待,因为GenServer 继续工作。
  2. 主管:您可以使用 Supervisor监督调度员。
  3. 在调度程序中保持状态,例如指示:最常调用的pid、什么类型的事件使用比较频繁,在调度中添加一些逻辑..

缺点:

  1. 您创建了两个 handle_cast 而不是一个:一个用于调度,另一个用于实际执行工作。更多行代码 -> 你会失去可读性
  2. 您的一些进程将专门用于调度,另一些进程将专门用于完成这项工作..但所有这些进程都将来自同一个 genserver。 您有一个GenServer用于两种进程
  3. 专门用于分派(dispatch)作业的进程可能不需要维护状态。
  4. 您不能根据流程类型使用不同的主管策略..因为它们来自相同的 GenServer

如果我必须选择:我会在“客户端 api”端进行调度,因为它是一个更简单的模式。如果我需要维护 GenServercallcast 的状态,我会创建第二个专用于该状态的状态。

关于Elixir GenServer 转换到其他节点的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52363985/

相关文章:

elixir - 在 Ecto 查询中使用变量引用命名绑定(bind)

reference - ETS创建返回值

curl - 如何使用HTTPoison在Elixir中执行DELETE?

tcp - 如何从命令行将主机名传递给 gen_tcp

elixir - 每次测试后停止 GenServer

macros - 如何动态创建具有功能的模块

ruby - 是否有等效于 Rails `try` 函数的 Elixir?

elixir - 如何从字符串中删除换行符?

postgresql - 如何在 Ecto 片段语句中使用带时区的 date_trunc

elixir - 如何在 Phoenix 应用程序启动时预填充数据库?