防止重复的命名进程

时间:2016-10-02 08:59:43

标签: elixir phoenix-framework otp supervisor

我有一个elixir(Phoenix)应用程序,它定期为用户检索分析数据。

我有一个AnalyticSupervisor来监督AnalyticWorker

defmodule AnalyticsSupervisor do
  use Supervisor

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

  def init(_) do
    children = [
      worker(AnalyticsWorker, [])
    ]

    supervise(children, strategy: :simple_one_for_one)
  end

  def start_worker(user) do
    Supervisor.start_child(:analytics_supervisor, [user])
  end
end

AnalyticWorker正在使用gproc作为流程注册表来创建动态流程名称并对分析调用进行排队。

defmodule AnalyticsWorker do
  use GenServer

  def start_link(user) do
    GenServer.start_link(__MODULE__, user, name: via_tuple(user))
  end

  defp via_tuple(user) do
    {:via, :gproc, {:n, :l, {:analytics_worker, user.id}}}
  end

  def init(user) do
    queue_analytic_call(user)
    {:ok, user}
  end

  def queue_analytic_call(user) do
    :timer.apply_after(50000, __MODULE__, :call_anlaytics, [user])
  end
end

启动我的Phoenix应用程序时启动AnaylticSupervisor,并为任何现有用户排队分析调用。

问题是,如果我开始另一个iex会话,这也将启动主管和工作人员 - 我将最终为同一工作提供多个流程。

我认为使用gproc作为进程注册表,这将被阻止 - 但每个iex会话都在创建自己的进程注册表。

  • 如何确保流程是唯一的,无论它们是否被iex会话或我的Phoneix应用程序排队?

  • 有没有比我正在做的更好的方式来实现独特的预定工作?

1 个答案:

答案 0 :(得分:1)

通过运行“另一个iex实例”,您基本上是在创建新的erlang节点,该节点对其他运行的节点一无所知。

确保流程是唯一的一个选项,无论它们是否被iex会话或我的Phoneix应用程序排队都将附加随后启动iex正在运行的。假设原始流程始于:

#                           ⇓⇓⇓⇓⇓⇓⇓⇓⇓
MIX_ENV=prod elixir --sname analytics -S mix run --no-halt

iex附加到其上使用:

#       put resolvable host name here ⇓⇓⇓⇓⇓⇓⇓⇓⇓
iex --sname console --remsh analytics@localhost

由于第二个问题是a)同一OP中的第二个问题和b)基于高度意见,我建议你比较你已经存在的实现(通常的方法是使用{{1或者喜欢以确保唯一性):

此外,Task.Supervisor可能足以满足您的零费用要求。