通过 Genserver 的 cast 方法合并 API 的响应

Consolidate response of API's though cast method of Genserver

我正在尝试通过 Genserver 的 cast 方法异步调用一个 API 10 次。有人可以指导我如何收集 10 API 的响应并合并到一个元组列表中吗?

defmodule DataMonitor.RuleReceiver do
  use GenServer

  require Logger

  alias DataMonitor.{
    ProcessRuleSet
  }

  def init(state) do
    {:ok, state}
  end

  def start_link do
    GenServer.start_link(__MODULE__, [])
  end

  def process_rule_set(receiver_pid, {rule_set, company_id, auth_headers}) do
    GenServer.cast(receiver_pid, {rule_set, company_id, auth_headers})
  end

  def handle_cast({rule_set, company_id, auth_headers}, state) do
    result = ProcessRuleSet.process_rule_set(rule_set, company_id, auth_headers)
    {:noreply, state}
  end

end

Sender/Caller 模块

defmodule DataMonitor.RuleSender do
    def perform() do
      Enum.each(rule_sets, fn rule_set ->
        {:ok, pid} = RuleReceiver.start_link()
        RuleReceiver.process_rule_set(pid, {rule_set, company_id, auth_headers})
      end)
    end
end

though GenServer.cast/2 [...] how I can collect the responses

你本身不能。 Cast 请求是异步的并且 return 没有响应。从 cast 收集数据的唯一方法是引入一个存储(如 Agentets 或其他)并直接从 [=12] 存储值=]秒。这个解决方案有一个明显的缺点:它的工作流程是不确定的,人们可能不会假设所有 10 个响应在任何时候都被 处理和存储 。也就是说,在某些情况下 casts 甚至可能会丢失和未处理,您没有机会收到有关这方面的通知。没遇到过这种情况,不过也算是合法了。

因此,在这种特殊情况下,您可能应该只使用 GenServer.call/2 instead of cast, and collect responses directly in the iteration with Enum.map/2:

def perform() do
  Enum.map(rule_sets, fn rule_set ->
    {:ok, pid} = RuleReceiver.start_link()
    {pid, RuleReceiver.process_rule_set_call(...)}
  end)
end

作为结果,您将有 10 个元组 {pid, response}。我不确定在这里创建 10 个 GenServers 的原因是什么,为什么不使用命名 GenServers 来不打扰 pids,但这显然超出了这里的范围.