Erlang 了解Elixir badarg错误消息

Erlang 了解Elixir badarg错误消息,erlang,elixir,Erlang,Elixir,当尝试从DynamicSupervisor启动我的流程时,我收到以下错误: {:error, {:EXIT, {:badarg, [ {:erlang, :apply, [ BfgEngine.MarketService, :start_link, {{BfgEngine.MarketService, :start_link, ["1111"]}, :permanent, 5000, :worke

当尝试从
DynamicSupervisor
启动我的流程时,我收到以下错误:

{:error,
 {:EXIT,
  {:badarg,
   [
     {:erlang, :apply,
      [
        BfgEngine.MarketService,
        :start_link,
        {{BfgEngine.MarketService, :start_link, ["1111"]}, :permanent, 5000,
         :worker, [BfgEngine.MarketService]}
      ], []},
     {:supervisor, :do_start_child_i, 3, [file: 'supervisor.erl', line: 379]},
     {:supervisor, :handle_call, 3, [file: 'supervisor.erl', line: 404]},
     {:gen_server, :try_handle_call, 4, [file: 'gen_server.erl', line: 661]},
     {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 690]},
     {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}
   ]}}}
我使用的代码是:

  def start_market(market_id) do
    spec = {MarketService, market_id}
    DynamicSupervisor.start_child(__MODULE__, spec)
  end
然而,我不清楚出了什么问题。哪个函数的哪个参数不正确?如何分解并读取给定的错误消息

更新:

这是我的主管的初始方法:

  @impl true
  def init(initial_arg) do
    DynamicSupervisor.init(
      strategy: :one_for_one,
      extra_arguments: [initial_arg]
    )
  end
更新2: 这是市场服务的启动链接:

  def start_link(market_id) when is_bitstring(market_id) do
    GenServer.start_link(__MODULE__, market_id, name: via_tuple(market_id))
  end
Im使用默认的
child\u spec
Im从
GenServer

更新3: 改为:

  def start_market(market_id) do
    spec = {MarketService, market_id: market_id}
    DynamicSupervisor.start_child(__MODULE__, spec)
  end
  def start_market(market_id) do
    spec = {MarketService, :market_id, market_id}
    DynamicSupervisor.start_child(__MODULE__, spec)
  end
给出:

{:error,
 {:undef,
  [
    {BfgEngine.MarketService, :start_link, [[], [market_id: "222"]], []},
    {DynamicSupervisor, :start_child, 3,
     [file: 'lib/dynamic_supervisor.ex', line: 654]},
    {DynamicSupervisor, :handle_start_child, 2,
     [file: 'lib/dynamic_supervisor.ex', line: 640]},
    {:gen_server, :try_handle_call, 4, [file: 'gen_server.erl', line: 661]},
    {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 690]},
    {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}
  ]}}
** (ArgumentError) supervisors expect each child to be one of:

  * a module
  * a {module, arg} tuple
  * a child specification as a map with at least the :id and :start fields
  * or a tuple with 6 elements generated by Supervisor.Spec (deprecated)

Got: {BfgEngine.MarketService, :market_id, "222"}

    (elixir) lib/supervisor.ex:657: Supervisor.init_child/1
    (elixir) lib/supervisor.ex:744: Supervisor.child_spec/2
    (elixir) lib/dynamic_supervisor.ex:304: DynamicSupervisor.start_child/2
改为:

  def start_market(market_id) do
    spec = {MarketService, market_id: market_id}
    DynamicSupervisor.start_child(__MODULE__, spec)
  end
  def start_market(market_id) do
    spec = {MarketService, :market_id, market_id}
    DynamicSupervisor.start_child(__MODULE__, spec)
  end
给出:

{:error,
 {:undef,
  [
    {BfgEngine.MarketService, :start_link, [[], [market_id: "222"]], []},
    {DynamicSupervisor, :start_child, 3,
     [file: 'lib/dynamic_supervisor.ex', line: 654]},
    {DynamicSupervisor, :handle_start_child, 2,
     [file: 'lib/dynamic_supervisor.ex', line: 640]},
    {:gen_server, :try_handle_call, 4, [file: 'gen_server.erl', line: 661]},
    {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 690]},
    {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}
  ]}}
** (ArgumentError) supervisors expect each child to be one of:

  * a module
  * a {module, arg} tuple
  * a child specification as a map with at least the :id and :start fields
  * or a tuple with 6 elements generated by Supervisor.Spec (deprecated)

Got: {BfgEngine.MarketService, :market_id, "222"}

    (elixir) lib/supervisor.ex:657: Supervisor.init_child/1
    (elixir) lib/supervisor.ex:744: Supervisor.child_spec/2
    (elixir) lib/dynamic_supervisor.ex:304: DynamicSupervisor.start_child/2

很难从发布的代码中分辨出来,但您能否尝试将
start\u market
更改为:

  def start_market(market_id) do
    spec = {MarketService, :market_id, market_id}
    DynamicSupervisor.start_child(__MODULE__, spec)
  end
更新(以下是两个选项):


当有三个参数
BfgEngine.MarketService
:start_link
{{BfgEngine.MarketService,:start_link,[“1111”]},:permanent,5000,:worker,[bfgengingine.MarketService]}时,您得到了函数
badarg
的异常
并且它发生在函数
主管:do\u start\u child\u i/3

函数
erlang:apply/3
的参数应该是MFA a a.k.a模块、函数、参数<代码>{BfgEngine.MarketService,:start_link,[“1111”]},:permanent,5000,:worker,[BfgEngine.MarketService]}不是参数,因为它显然不是参数列表。从您的代码中,我可以猜到错误是变量
spec
的内容。你应该提供一些道具列表或地图。我不知道,您应该更仔细地阅读
DynamicSupervisor
的文档。

错误消息 在理解Elixir抛出的错误消息时,您可以参考。关于从中学习一些Erlang For Great Good的部分可以帮助您。
@Hynek-Pichi Vychodil
的答案也是准确的

你的具体问题 正如
@Milan Jaric
所述,您的错误可能来自:

  def start_market(market_id) do
    spec = {MarketService, market_id}
    DynamicSupervisor.start_child(__MODULE__, spec)
  end
但不仅如此
DynamicSupervisor.start\u child(\uu模块,spec)
正在调用
MarketService.start\u link/1
! 您的问题在于DynamicSupervisor模块中的此函数与您在MarketService.start\u link/1中解析值的方式的组合:

  def start_link(market_id) when is_bitstring(market_id) do
    GenServer.start_link(__MODULE__, market_id, name: via_tuple(market_id))
  end
事实上,如果您还正确实现了MarketService.init/1,那么这段代码应该可以工作。我无法重现这个错误。您确定
market\u id
真的是位字符串吗

就我个人而言,我的代码基于:

如您所见,他们建议在此处使用关键字列表:

spec = {MyWorker, foo: foo, bar: bar, baz: baz}
仅当您已实现MyWorker时,它才起作用。按如下方式启动链接/1:

def start_link(args) do
   foo = Keyword.fetch!(args, :foo)
   bar = Keyword.fetch!(args, :bar)
   baz = Keyword.fetch!(args, :baz)
   Genserver.start_link(__MODULE__, {foo, bar, baz}, [])

def init({foo, bar, baz}) do
   # do something...
   state = {foo, bar, baz}
   {:ok, state}
  def init(market_id) do
     # do something... Let's keep it simple for the example:
     state = market_id
     {:ok, state}
  end
在您的情况下,如果您将start_market/1更改为:

  def start_market(market_id) do
      spec = {MarketService, market_id: market_id}
      DynamicSupervisor.start_child(__MODULE__, spec)
  end
它将不工作,因为此MarketService.start\u链接/1将失败:

 def start_link(market_id) when is_bitstring(market_id) do
    GenServer.start_link(__MODULE__, market_id, name: via_tuple(market_id))
  end
这里的market\u id不是一个
位字符串,而是一个关键字列表。因此,您必须将MarketService.start\u link/1函数修改为:

  def start_link(args) when is_list(args) do
    market_id = Keyword.fetch!(args, :market_id)
    GenServer.start_link(__MODULE__, market_id, name: via_tuple(market_id))
  end
并编写一个MarketService.init/1,如下所示:

def start_link(args) do
   foo = Keyword.fetch!(args, :foo)
   bar = Keyword.fetch!(args, :bar)
   baz = Keyword.fetch!(args, :baz)
   Genserver.start_link(__MODULE__, {foo, bar, baz}, [])

def init({foo, bar, baz}) do
   # do something...
   state = {foo, bar, baz}
   {:ok, state}
  def init(market_id) do
     # do something... Let's keep it simple for the example:
     state = market_id
     {:ok, state}
  end
有用的资源
  • 一本关于长生不老药的GenServer和Supervisors的好书
  • …和

您是否也可以分享主管的
init
功能的定义?问题出在
MarketService的
start\u链接中。这里要看的是你的开始链接函数和你的孩子规范。你能把它们添加到你的帖子中吗?我已经更新了一些例子,现在我发现了一个不同的错误。你不能使用我的代码。它应该只是元组
{MarketService,:market\u id,market\u id}
而不是
{MarketService,market\u id:market\u id}
,这是两种不同的数据结构。请注意:market\u id atom后面的逗号!我知道这是旧的,但是,我更新了答案。这应该是正确的