-1

我刚开始使用 Elixir,想用 Plug 构建一个非常简单的 API。我使用本指南来启动和运行一个非常简单的 API。


基本上,我面临的问题是:qs,每当我send/2queue_service.ex. 我想要实现的是一个持续存在的过程,以便我可以跨请求维护状态。


在我的router.ex文件中,我有:

defmodule SecondQueue.Router do
  use Plug.Router

  alias SecondQueue.Plug.VerifyParams
  alias SecondQueue.QueueService

  plug Plug.Parsers, parsers: [:urlencoded, :multipart]
  plug :match
  plug :dispatch


  get "/receive-message" do
    # gather query parameters from connection
    queue = Map.get(conn.params, "queue")
    message = Map.get(conn.params, "message")

    # handle the params
    QueueService.handle_incoming(queue, message)

    send_resp(conn, 201, "Created")
  end
end


然后在内部queue_service.ex,我启动队列进程,将其注册到 的原子:qs,然后希望稍后能够通过请求调用的函数进入该进程。我有:

defmodule SecondQueue.QueueService do
  alias SecondQueue.QueueStore
  use Agent

  {:ok, agent_pid} = QueueStore.start_queues_link()
  Process.register(agent_pid, :qs)

  def handle_incoming(queue, message) do
    queue_atom = String.to_atom(queue)
    send(:qs, {:put, queue_atom, "success"})
  end
end

最后,在 中queue_store.ex,我实际上定义了我想要存储状态的进程,并运行一个循环以使其保持活动状态,并准备好接收消息。我有:

defmodule SecondQueue.QueueStore do
  def start_queues_link() do
    Task.start_link(fn -> queues_loop(%{}) end)
  end

  defp queues_loop(map) do
    receive do
      {:get, key, caller} ->
        send caller, Map.get(map, key)
        queues_loop(map)
      {:put, key, value} ->
        IO.puts("i am here")
        queues_loop(Map.put(map, key, value))
    end
  end
end

更新:
Github 仓库:https ://github.com/qarthandgi/test-second-queue

4

1 回答 1

3

Elixir 是一种编译语言。下面的代码在编译阶段执行;运行时没有启动任何进程。

defmodule SecondQueue.QueueService do
  ...
  {:ok, agent_pid} = QueueStore.start_queues_link()
  Process.register(agent_pid, :qs)
  ...
end

相反,您需要将此代码放入一个函数并显式调用此函数以启动QueueStore(直接或通过将其插入应用程序的监督树)。

于 2019-08-23T14:02:07.103 回答