【问题标题】:How to restart a supervised task that crashes如何重新启动崩溃的监督任务
【发布时间】:2016-05-27 09:06:36
【问题描述】:
{:ok, tas} = Task.Supervisor.start_link(restart: :transient, max_restarts: 4)
a = 1
Task.Supervisor.async_nolink(tas, fn -> IO.puts "#{a}..." end)
Task.Supervisor.async_nolink(tas, fn ->
  IO.puts "Not Restarting :( "
  1 = 2
end)
a =  a + 1
Task.Supervisor.async_nolink(tas, fn -> IO.puts "#{a}.." end)
a =  a + 1
Task.Supervisor.async_nolink(tas, fn -> IO.puts "#{a}.." end)

restart: :transient 选项似乎没有任何作用。

我有几个任务Task.async(fn(x) -> fetch_info(x) end 发出http 请求以获取多个资源,并且有超时错误。最好重试那些失败的任务,而不是使用tryrescue

我认为async_nolink 是我得到的最接近的,不会导致进程崩溃。如果无法使用Task,我们是否有更简单的方法使用Supervisor,它启动多个进程,一旦它们的工作完成就存在并在它们失败时重新启动它们?

【问题讨论】:

    标签: elixir erlang-otp


    【解决方案1】:

    我不认为任务是您想要的最佳选择。在文档Task Docs 中说:

    这个模块定义了一个监督者,可以用来动态监督任务。在幕后,这个模块被实现为一个 :simple_one_for_one 监督者,其中工人是临时的(即他们死后不会重新启动)。

    :restart - 重启策略,可以是:temporary(默认)、:transient 或:permanent。检查 Supervisor.Spec 了解更多信息。默认为临时的,因为大多数任务在崩溃后无法有效地重新启动;

    您应该研究 GenServer 并建立一个工人池,也许是 GenServer Intro。 《Little Elixir and OTP Guide》这本书很不错,我已经阅读了大约一半,它为 OTP、分发和主管提供了良好的基础。

    编辑:我刚刚检查了这本书,找不到任何关于重新启动任务的信息,只是进程。

    【讨论】:

      【解决方案2】:

      您只需要使用Task.Supervisor.start_child 而不是Task.Supervisor.async_nolink 就可以让孩子正确重启:

      {:ok, tas} = Task.Supervisor.start_link(restart: :transient, max_restarts: 4)
      
      Task.Supervisor.start_child(tas, fn -> 1 = 2 end) 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-29
        • 1970-01-01
        • 1970-01-01
        • 2021-05-10
        相关资源
        最近更新 更多