我想尝试在Supervisor中启动Agent,其中一行用于测试目的:
iex(1)> {:ok, pid} = Supervisor.start_link([{Agent, [fn -> 42 end, name: :test]}], strategy: :one_for_one)
** (EXIT from #PID<0.115.0>) evaluator process exited with reason: shutdown: failed to start child: Agent
** (EXIT) an exception was raised:
** (FunctionClauseError) no function clause matching in Agent.start_link/2
(elixir) lib/agent.ex:215: Agent.start_link([#Function<20.99386804/0 in :erl_eval.expr/5>, {:name, :test}], [])
(stdlib) supervisor.erl:365: :supervisor.do_start_child/2
(stdlib) supervisor.erl:348: :supervisor.start_children/3
(stdlib) supervisor.erl:314: :supervisor.init_children/2
(stdlib) gen_server.erl:365: :gen_server.init_it/2
(stdlib) gen_server.erl:333: :gen_server.init_it/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
请注意Supervisor.start_link([{Agent, [fn -> 42 end, name: :test]}], strategy: :one_for_one)
,此代码向我抛出错误,是否存在语法问题?
我正在使用Elixir 1.5
答案 0 :(得分:2)
发生这种情况的原因是Supervisor.start_link/2
的类型为start_link([:supervisor.child_spec | {module, term} | module], options) :: on_start
根据您传递数据的方式,您似乎正在尝试使用{module, term}
。 term
将传递给module
的{{1}}函数的第一个参数。start_link/2
所以,相当于你试图做的是Agent.start_link([fn -> 42 end, name: :test], [])
(你可以在错误中看到这一点)。您将所有内容传递给函数的第一个参数,在这种情况下,不允许获取列表。
您将要使用:supervisor.child_spec
路径。以下内容应该适合您。
import Supervisor.Spec
children = [
worker(Agent, [fn -> 42 end, name: :test])
]
opts = [strategy: :one_for_one]
Supervisor.start_link(children, opts)
修改强>
您刚才在评论中提到您使用的是Elixir 1.5。
您将要创建一个包含Agent
行为的模块。
defmodule MyAgent do
use Agent
def add(pid, n) do
Agent.update(pid, fn state -> state + n end)
end
def subtract(pid, n) do
Agent.update(pid, fn state -> state - n end)
end
def start_link(fun, opts) do
Agent.start_link(fun, opts)
end
# This function is important because it is how we know how to pass the various options to the actual start_link function.
def child_spec([fun | rest]) do
%{
id: __MODULE__,
# The fun and rest here are the function we pass in and then the options. Feel free to do this how you want.
start: {__MODULE__, :start_link, [fun, rest]},
restart: :permanent,
shutdown: 5000,
type: :worker
}
end
end
现在调用Supervisor.start_link([{My Agent, [fn -> 42 end, name: :test]}], strategy: :one_for_one)
应该返回{:ok, pid}
。