elixir - 我的申请开始了,但马上就结束了

标签 elixir

我不确定我做错了什么,但我已经创建了一个 Elixir 应用程序,如果我运行它:

iex -S mix

应用程序加载主管,主管加载连接到rabbitmq 的 gen_server 并继续监听消息,但是如果我运行应用程序
mix app.start

或者
mix run

主管已加载,工作人员已启动并连接到rabbitmq,但它立即结束,没有任何错误,示例代码:

混合文件
defmodule Sample.Mixfile do
  use Mix.Project

  def project do
    [app: :sample,
     version: "0.0.1",
     elixir: "~> 1.0",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     deps: deps]
  end

  # Configuration for the OTP application
  #
  # Type `mix help compile.app` for more information
  def application do
    [applications: [:logger, :rabbit_common, :ssl, :erlcloud, :amqp],
     mod: {Sample, []}]
  end

  # Dependencies can be Hex packages:
  #
  #   {:mydep, "~> 0.3.0"}
  #
  # Or git/path repositories:
  #
  #   {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"}
  #
  # Type `mix help deps` for more examples and options
  defp deps do
    [
      {:erlcloud, git: "https://github.com/gleber/erlcloud" },
      {:amqp, "~> 0.1.1"}
    ]
  end
end

示例.ex 文件
defmodule Sample do
  use Application
  require Logger

  def start(_type, _args) do
    IO.puts("Starting App")
    Sample.Supervisor.start_link
  end
end

主管.ex
defmodule Sample.Supervisor do
  use Supervisor

  def start_link do
    Supervisor.start_link(__MODULE__, :ok)
  end

  def init(:ok) do
    children = [
      worker(Sample.Worker, [[name: :sample_worker]])
    ]

    # one_for_one: If one process dies, the supervisor restarts it without affecting the others
    supervise(children, strategy: :one_for_one)
  end
end

和 worker .ex
defmodule Sample.Worker do
  use GenServer
  use AMQP

  @exchange    "exchange_name"
  @queue       "queue_name"

  ### Client API

  @doc """
  Starts the worker who consumes rabbitmq messages on exchange @exchange
  """
  def start_link(opts \\ []) do
    GenServer.start_link(__MODULE__, :ok, opts)
  end

  def stop do
    GenServer.cast(__MODULE__, :stop)
  end

  ### Server Callbacks

  def init(:ok) do
    {:ok, connection} = Connection.open
    {:ok, channel} = Channel.open(connection)
    Queue.declare(channel, @queue, durable: true, arguments: [])
    Exchange.direct(channel, @exchange, durable: true)
    Queue.bind(channel, @queue, @exchange)

    # Register the GenServer process as a consumer
    {:ok, _consumer_tag} = Basic.consume(channel, @queue)
    {:ok, channel}
  end

  # Confirmation sent by the broker after registering this process as a consumer
  def handle_info({:basic_consume_ok, %{consumer_tag: consumer_tag}}, channel) do
    IO.puts("#{__MODULE__} consumer connected")
    {:noreply, channel}
  end

  # Sent by the broker when the consumer is unexpectedly cancelled (such as after a queue deletion)
  def handle_info({:basic_cancel, %{consumer_tag: consumer_tag}}, channel) do
    IO.puts("#{__MODULE__} consumer unexpectedly cancelled")
    {:stop, :normal, channel}
  end

  # Confirmation sent by the broker to the consumer process after a Basic.cancel
  def handle_info({:basic_cancel_ok, %{consumer_tag: consumer_tag}}, channel) do
    IO.puts("#{__MODULE__} consumer Basic.cancel")
    {:noreply, channel}
  end

  # Basic deliverying of a data package
  def handle_info({:basic_deliver, payload, %{delivery_tag: tag, redelivered: redelivered}}, channel) do
    spawn fn -> consume(channel, tag, redelivered, payload) end
    {:noreply, channel}
  end

  # Catches all other messages         
  def handle_info(message, state) do
    IO.puts("#{__MODULE__} handle_info called with #{message}")
    {:noreply, state}
  end

  def handle_call(message, _from, state) do
    IO.puts("#{__MODULE__} handle_call called with #{message}")
    {:reply, :response, state}
  end

  def handle_cast(message, state) do
    IO.puts("#{__MODULE__} handle_cast called with #{message}")
    {:noreply, state}
  end

  ### Implementation

  defp consume(channel, tag, redelivered, payload) do
    try do
      IO.puts("Consuming #{payload}")
      Basic.ack channel, tag
    rescue
      exception ->
        # Requeue unless it's a redelivered message.                                                                                                        
        # This means we will retry consuming a message once in case of exception                                                 
        # before we give up and have it moved to the error queue
        Basic.reject channel, tag, requeue: not redelivered
        IO.puts "Error received: #{exception}"
    end
  end
end

最佳答案

mix run是正确的命令。与 elixir 一样可执行文件,你需要通过 --no-halt :

mix run --no-halt

关于elixir - 我的申请开始了,但马上就结束了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31198882/

相关文章:

elixir - 如何在 Elixir 控制台中定义命名函数而不获取 ** (ArgumentError) cannot call def/2 outside module?

elixir - 为什么 Elixir 的 nil 实现了 Access 行为?

testing - Elixir - 测试完整的脚本

elixir - 使用 Coinbase API (Elixir) 生成有效 HMAC 签名的问题

elixir - 如何在 Elixir 中生成数字序列?

elixir - 通过管道传输到 Enum.into 的范围会引发警告

datetime - 如何在 Elixir 中模拟当前时间

elixir - 如何从任何链接进程获得任何崩溃通知?

Elixir:混合别名,一个别名中有两个 `run` 任务

macros - Elixir 宏和 bind_quoted