生成一个受监督的进程以定期报告心跳
Spawning a supervised process to report a heartbeat periodically
我正在尝试生成一个进程,该进程将每五秒 post 一个 HTTP 请求以向服务器报告它的心跳。我的代码是:
defmodule MyModule.Heartbeat do
def start_link do
spawn_link(fn ->
:timer.apply_interval(:timer.seconds(5), __MODULE__, :beat, [])
end)
end
defp beat do
HTTPoison.post "https://myserver/heartbeat
end
end
defmodule MyModule.Supervisor do
use Supervisor
def start_link do
Supervisor.start_link(__MODULE__, :ok)
end
def init(:ok) do
children = [
worker(MyModule.Heartbeat, [])
]
supervise(children, strategy: :one_for_one)
end
end
但是,当我尝试启动该应用程序时,它退出并出现以下错误:
[info] Application my_module exited: MyModule.start(:normal, []) returned an error: shutdown: failed to start child: MyModule.Heartbeat
** (EXIT) #PID<0.535.0>
我只需要一些进程,它将 运行 作为监督树的一部分,并在指定的时间间隔内发送请求。它本身不需要能够接收任何消息,我也不太在意具体的实现。
任何人都可以提出我在这里做错了什么,阻止了这个过程的启动,是否有更好的方法来实现这个?
您的代码中有 3 个错误:
:timer.apply_interval/4
returns 立即,因此匿名
在 MyModule.Heartbeat.start_link/0
中传递给 spawn_link
的函数终止
执行该行后不久,导致 :timer
从中删除间隔
它的队列,并且从未调用 MyModule.Heartbeat.beat/0
。
你可以通过在最后添加一个 :timer.sleep(:infinity)
来解决这个问题
表达式,它使您的进程永远休眠。
MyModule.Heartbeat.beat/0
需要是一个 public 函数,这样
传递给 spawn_link
的匿名函数可以调用它。
MyModule.Heartbeat.start_link/0
需要 return {:ok, pid}
才能成功。
spawn_link
return只是一个 pid。
经过这 3 次更改后的最终代码:
defmodule MyModule.Heartbeat do
def start_link do
pid = spawn_link(fn ->
:timer.apply_interval(:timer.seconds(5), __MODULE__, :beat, [])
:timer.sleep(:infinity)
end)
{:ok, pid}
end
def beat do
IO.puts "beat"
end
end
defmodule MyModule.Supervisor do
use Supervisor
def start_link do
Supervisor.start_link(__MODULE__, :ok)
end
def init(:ok) do
children = [
worker(MyModule.Heartbeat, [])
]
supervise(children, strategy: :one_for_one)
end
end
输出:
iex(1)> MyModule.Supervisor.start_link
{:ok, #PID<0.84.0>}
iex(2)> beat
beat
beat
beat
我不确定你是否需要所有这些设置作为函数引发的异常
传递给 :timer.apply_interval
不影响调用过程。这
以下脚本不断尝试 运行 该函数,即使它总是引发一个
异常:
defmodule Beat do
def beat do
raise "hey"
end
end
:timer.apply_interval(:timer.seconds(1), Beat, :beat, [])
:timer.sleep(:infinity)
输出:
$ elixir a.exs
16:00:43.207 [error] Process #PID<0.53.0> raised an exception
** (RuntimeError) hey
a.exs:3: Beat.beat/0
16:00:44.193 [error] Process #PID<0.54.0> raised an exception
** (RuntimeError) hey
a.exs:3: Beat.beat/0
16:00:45.193 [error] Process #PID<0.55.0> raised an exception
** (RuntimeError) hey
a.exs:3: Beat.beat/0
我正在尝试生成一个进程,该进程将每五秒 post 一个 HTTP 请求以向服务器报告它的心跳。我的代码是:
defmodule MyModule.Heartbeat do
def start_link do
spawn_link(fn ->
:timer.apply_interval(:timer.seconds(5), __MODULE__, :beat, [])
end)
end
defp beat do
HTTPoison.post "https://myserver/heartbeat
end
end
defmodule MyModule.Supervisor do
use Supervisor
def start_link do
Supervisor.start_link(__MODULE__, :ok)
end
def init(:ok) do
children = [
worker(MyModule.Heartbeat, [])
]
supervise(children, strategy: :one_for_one)
end
end
但是,当我尝试启动该应用程序时,它退出并出现以下错误:
[info] Application my_module exited: MyModule.start(:normal, []) returned an error: shutdown: failed to start child: MyModule.Heartbeat
** (EXIT) #PID<0.535.0>
我只需要一些进程,它将 运行 作为监督树的一部分,并在指定的时间间隔内发送请求。它本身不需要能够接收任何消息,我也不太在意具体的实现。
任何人都可以提出我在这里做错了什么,阻止了这个过程的启动,是否有更好的方法来实现这个?
您的代码中有 3 个错误:
:timer.apply_interval/4
returns 立即,因此匿名 在MyModule.Heartbeat.start_link/0
中传递给spawn_link
的函数终止 执行该行后不久,导致:timer
从中删除间隔 它的队列,并且从未调用MyModule.Heartbeat.beat/0
。你可以通过在最后添加一个
:timer.sleep(:infinity)
来解决这个问题 表达式,它使您的进程永远休眠。MyModule.Heartbeat.beat/0
需要是一个 public 函数,这样 传递给spawn_link
的匿名函数可以调用它。MyModule.Heartbeat.start_link/0
需要 return{:ok, pid}
才能成功。spawn_link
return只是一个 pid。
经过这 3 次更改后的最终代码:
defmodule MyModule.Heartbeat do
def start_link do
pid = spawn_link(fn ->
:timer.apply_interval(:timer.seconds(5), __MODULE__, :beat, [])
:timer.sleep(:infinity)
end)
{:ok, pid}
end
def beat do
IO.puts "beat"
end
end
defmodule MyModule.Supervisor do
use Supervisor
def start_link do
Supervisor.start_link(__MODULE__, :ok)
end
def init(:ok) do
children = [
worker(MyModule.Heartbeat, [])
]
supervise(children, strategy: :one_for_one)
end
end
输出:
iex(1)> MyModule.Supervisor.start_link
{:ok, #PID<0.84.0>}
iex(2)> beat
beat
beat
beat
我不确定你是否需要所有这些设置作为函数引发的异常
传递给 :timer.apply_interval
不影响调用过程。这
以下脚本不断尝试 运行 该函数,即使它总是引发一个
异常:
defmodule Beat do
def beat do
raise "hey"
end
end
:timer.apply_interval(:timer.seconds(1), Beat, :beat, [])
:timer.sleep(:infinity)
输出:
$ elixir a.exs
16:00:43.207 [error] Process #PID<0.53.0> raised an exception
** (RuntimeError) hey
a.exs:3: Beat.beat/0
16:00:44.193 [error] Process #PID<0.54.0> raised an exception
** (RuntimeError) hey
a.exs:3: Beat.beat/0
16:00:45.193 [error] Process #PID<0.55.0> raised an exception
** (RuntimeError) hey
a.exs:3: Beat.beat/0