代码之家  ›  专栏  ›  技术社区  ›  David Magalhães cpu

当DynamicSupervisor启动时启动workers

  •  1
  • David Magalhães cpu  · 技术社区  · 7 年前

    Process.send_after/3 以一定的时间精度发送推送通知。

    在某些情况下,例如,当我发布没有热交换功能的新版本时,我希望保留所有尚未完成的工作进程的记录,并且当DynamicSupervisor开始使用DETS中保存的相同状态再次创建所有这些工作进程时。

    DynamicSupervisor 从一开始就不支持工人,我应该实施 start_child 要启动一个新的worker,但不知道如何将DynamicSupervisor的启动与同一模块上的这些worker的启动集成起来。

    我尝试过不同的方法,但是没有成功( Task.async , Process.send_after 等)。

    编辑:我发现了一个小问题(应为%x:1,y:2}),正在接收[x:1,y:2]

    ...
    
    def init(arg) do
      Task.async(fn ->
        start_lost_children()
      end)
    
      DynamicSupervisor.init(arg)
    end
    
    def start_child(data) do
      spec = {MyApp.Worker, %{data: data}}
    
      DynamicSupervisor.start_child(__MODULE__, spec)
    end
    
    ...
    

    这是我得到的错误消息,虽然没有影响DynamicSupervisor的行为。

    [error] DynamicSupervisor received unexpected message: {#Reference<0.2565843855.2975858690.212433>, :ok}
    
    [error] DynamicSupervisor received unexpected message: {:DOWN, #Reference<0.2565843855.2975858690.212433>, :process, #PID<0.593.0>, :normal}
    

    这个 :ok start_lost_children/0 返回。

    如果我实施 handle_info/2

    2 回复  |  直到 7 年前
        1
  •  1
  •   Aleksei Matiushkin    7 年前

    我把这个放在这里主要是为了代码格式化;下面的代码在我的项目中的相同条件下在相同的情况下对我有效。我不确定它是否有用,因为您已经明确提到您尝试过sorta这种方法,但是由于OP中没有任何代码可以与之相比,我们来看看。

    启动任务的流程应该实现这两个 handle_info/2

    @doc false
    # Task finished {#Reference<0.0.1.6335>, :ok}
    def handle_info({_pid, _payload}, state),
      do: {:noreply, state}
    
    @doc false
    def handle_info({:DOWN, _ref, :process, _pid, :normal}, state),
      do: {:noreply, state}
    

    可选地,您可能希望显式地为除此之外的其他返回状态处理后者 :normal .


    init 不是合适的地方 Task.async/1 因为 init/1 是从进程调用的回调,它启动您的自定义 DynamicSupervisor info 返回消息(请参阅错误消息报告 动态监视器 )

    下面的方法应该有效(假设两种方法都有效 处理信息/2 已实现):

    def start_link(arg) do
      with link <- DynamicSupervisor.start_link(...) do
        Task.async(...)
        link
      end
    end
    
    @impl true
    def init(args) do
      DynamicSupervisor.init(args)
    end
    
        2
  •  0
  •   Pavel Tsiukhtsiayeu    6 年前

    Task.async/1 Task.await/2 Task.yield/2 .

    尝试 Task.start/1 -仅当任务用于副作用(即对返回的结果不感兴趣)且不应将其链接到当前进程时才使用。