【发布时间】:2017-01-09 18:30:04
【问题描述】:
我已经缩小了问题的大小,因为它太大了。代码如下:
defmodule MayRaiseGenServer do
use GenServer
def start_link do
IO.puts "started MyServer, name is #{__MODULE__}"
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
def maybe_will_raise do
GenServer.call(__MODULE__, :maybe_will_raise)
end
def handle_call(:maybe_will_raise,_from, state) do
IO.puts "maybe_will_raise called!"
:random.seed(:erlang.now)
number = Enum.to_list(1..100) |> Enum.shuffle |> List.first
IO.puts "number is #{number}"
if rem(number,2) != 0 do
raise "#{number}"
end
{:reply, {"You got lucky"}, state}
end
end
defmodule MayRaiseSupervisor do
use Supervisor
def start_link([]) do
IO.puts "starting supervisor, name is #{__MODULE__}"
Supervisor.start_link(__MODULE__, [])
end
def init(arg) do
IO.puts "initted with arg: #{arg}"
children = [
worker(MayRaiseGenServer, [])
]
supervise(children, strategy: :one_for_one, restart: :transient, name: __MODULE__)
end
end
MayRaiseSupervisor.start_link([])
IO.inspect MayRaiseGenServer.maybe_will_raise
:timer.sleep(2000)
IO.puts "after sleep"
一开始只看到一次启动GenServer的提示,现在又看到了。这是输出:
starting supervisor, name is Elixir.MayRaiseSupervisor
initted with arg:
started MyServer, name is Elixir.MayRaiseGenServer
maybe_will_raise called!
number is 14
started MyServer, name is Elixir.MayRaiseGenServer
11:32:28.807 [error] GenServer MayRaiseGenServer terminating
** (RuntimeError) 14
lib/mini.ex:20: MayRaiseGenServer.handle_call/3
(stdlib) gen_server.erl:615: :gen_server.try_handle_call/4
(stdlib) gen_server.erl:647: :gen_server.handle_msg/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: :maybe_will_raise
State: []
** (exit) exited in: GenServer.call(MayRaiseGenServer, :maybe_will_raise, 5000)
** (EXIT) an exception was raised:
** (RuntimeError) 14
lib/mini.ex:20: MayRaiseGenServer.handle_call/3
(stdlib) gen_server.erl:615: :gen_server.try_handle_call/4
(stdlib) gen_server.erl:647: :gen_server.handle_msg/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
(elixir) lib/gen_server.ex:604: GenServer.call/3
lib/mini.ex:45: (file)
(elixir) lib/code.ex:363: Code.require_file/2
从上面的输出中,我不太清楚会发生什么。根据 IO 上显示的消息,看起来 GenServer 已重新启动,但为什么再次抛出异常?另外,在这段代码中:
MayRaiseSupervisor.start_link([])
IO.inspect MayRaiseGenServer.maybe_will_raise
:timer.sleep(2000)
IO.puts "after sleep"
如果方法调用MayRaiseGenServer.maybe_will_raise 确实会引发错误,看起来就像后面的行,带有timer.sleep 和IO.puts 的行将不再运行。即使我更改代码以尝试处理异常,如下所示:
MayRaiseSupervisor.start_link([])
try do
IO.inspect MayRaiseGenServer.maybe_will_raise
rescue
RuntimeError -> IO.puts "there was an error"
end
:timer.sleep(2000)
IO.puts "after sleep"
我似乎仍然无法到达最后一个IO.puts(如果出现错误)。有没有办法处理对maybe_will_raise 的调用,让我能够处理它引发错误并继续执行?我猜主管在重新启动时不会自动重试一段代码。
【问题讨论】:
-
好吧,根据输出,服务器已重新启动,因为有 2 行带有
started MyServer。您也可以通过调用:Process.alive? Process.whereis(MayRaiseGenServer)来检查。如果您的服务器正在运行,它将返回 true。 -
我注意到了不同的 PID,但
IO.puts "started MyServer"输出应该不会再次出现吗?
标签: elixir erlang-otp