Elixir Redix 基于名称的池示例 - 主管签名不存在

Posted

技术标签:

【中文标题】Elixir Redix 基于名称的池示例 - 主管签名不存在【英文标题】:Elixir Redix name-based pool example - Supervisor signature doesn't exist 【发布时间】:2019-03-10 04:14:20 【问题描述】:

所以我在遵循这个“超级简单”的例子时遇到了麻烦。 Elixir 新手(主要来自 Ruby 背景)。

只是尝试在主应用程序监督树下创建一个 redis 连接池设置以用于活动用户会话,但实际上 redis 将更加有用,因此我正在尝试正确设置此设置。

This line:
start: Supervisor, :start_link, [children_redix]

 Gives me the following error:

** (Mix) Could not start application gametime: 
Gametime.Application.start(:normal, []) returned an error: shutdown: 
failed to start child: RedixSupervisor
** (EXIT) an exception was raised:
    ** (UndefinedFunctionError) function Supervisor.start_link/1 is undefined or private
        (elixir) Supervisor.start_link([%id: Redix, 0, start: Redix, :start_link, [[name: :redix_0]], type: :worker, %id: Redix, 1, start: Redix, :start_link, [[name: :redix_1]], type: :worker, %id: Redix, 2, start: Redix, :start_link, [[name: :redix_2]], type: :worker, %id: Redix, 3, start: Redix, :start_link, [[name: :redix_3]], type: :worker, %id: Redix, 4, start: Redix, :start_link, [[name: :redix_4]], type: :worker])

如果我从上一行的 children_redix 中删除方括号,我会得到:

 ** (UndefinedFunctionError) function Supervisor.start_link/5 is undefined or private

这是我正在关注的文档:

https://hexdocs.pm/redix/real-world-usage.html

这是应用启动函数:

   defmodule Gametime.Application do                                                            
      use Application                                                                            
      use Supervisor                                                                           


      def start(_type, _args) do                                                                 

        pool_size = 5                                                                            

        #creates redix children processes                                                                                   
        children_redix =                                                                         
          for i <- 0..(pool_size - 1) do                                                         
            Supervisor.child_spec(Redix, name: :"redix_#i", id: Redix, i)                  
          end                                                                                    

        children = [                                                                             
          # child spec for the supervisor I am trying to add to the main supervision tree,                                                                                
          %                                                                                     
            id: RedixSupervisor,                                                                 
            type: :supervisor,                                                                   
            start: Supervisor, :start_link, [children_redix]                                   
          ,                                                                                     

          # This way is now deprecated  - although this was generated by phoenix so not going to touch this just yet.                                       
          supervisor(Gametime.Repo, []),                                                                                    
          supervisor(GametimeWeb.Endpoint, []),                                                  

          # Start your own worker by calling: Gametime.Worker.start_link(arg1, arg2, arg3)       
          # worker(Gametime.Worker, [arg1, arg2, arg3]),                                         
        ]                                                                                        


        opts = [strategy: :one_for_one, name: Gametime.Supervisor]                                                                                             
        Supervisor.start_link(children, opts)                                                    
      end 

我只是不确定我哪里出错了。我觉得这可能是文档中关于我应该知道什么的假设——但不幸的是,我不知道我不知道什么。任何帮助都会很棒 - 干杯。

【问题讨论】:

【参考方案1】:

哇——所以我猜这些文档已经过时了。经历了一些痛苦来解决这个问题 - 所以我想我会分享。

...   %                                                                                                
      id: RedixSupervisor,                                                                            
      type: :supervisor,                                                                              
      start: Supervisor, :start_link, [  children_redix , [strategy: :one_for_one] ]                                                                        
    ,  ...

就是答案。文档似乎只是通过了 children_redix child_spec 映射 - 但这不是 Supervisor.start_link/2 期望的签名。

我可能会错过更多关于这个故事的内容,而且how to 中可能还有一些我没有注意到的内容,因为可能假设人们应该已经知道了什么。

干杯

【讨论】:

这是正确答案。文档已在 github.com/whatyouhide/redix/commit/… 中修复。【参考方案2】:

你可能需要包装:

Supervisor.child_spec(% id: RedixSupervisor, type: :supervisor, start: RedixSupervisor, :start_link, [children_redix] )

start 元组上使用你的 RedixSupervisor 模块,而不是通用的 Supervisor。从 RedixSupervisor 中定义的start_link/1 中,您将收到参数(在本例中为children_redix),您将在其中Supervisor.start_link,并使用init 函数中传递的子项作为参数

一个例子是:

defmodule RedixSupervisor do
  use Supervisor
  require Logger

  def start_link(children_redix) do
    Logger.info("RedixSupervisor Start Link")
    Supervisor.start_link(__MODULE__, children_redix, name: __MODULE__)
  end

  def init(children_redix) do
    children = children_redix
    Supervisor.init(children, strategy: :one_for_one)
  end
end

【讨论】:

以上是关于Elixir Redix 基于名称的池示例 - 主管签名不存在的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Elixir 的伞式应用程序名称放入记录器元数据中?

Elixir IEx shell,如何突破当前的“接收”块

DHCP——基于接口地址的池的DHCP

Elixir/Erlang 中的命名函数是不是有等效于 __MODULE__ 的方法?

Elixir 理解 GenServer

Elixir ecto 2 创建 many_to_many 关联