通过 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
收集数据的唯一方法是引入一个存储(如 Agent
或 ets
或其他)并直接从 [=12] 存储值=]秒。这个解决方案有一个明显的缺点:它的工作流程是不确定的,人们可能不会假设所有 10 个响应在任何时候都被 处理和存储 。也就是说,在某些情况下 cast
s 甚至可能会丢失和未处理,您没有机会收到有关这方面的通知。没遇到过这种情况,不过也算是合法了。
因此,在这种特殊情况下,您可能应该只使用 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 个 GenServer
s 的原因是什么,为什么不使用命名 GenServer
s 来不打扰 pid
s,但这显然超出了这里的范围.
我正在尝试通过 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
收集数据的唯一方法是引入一个存储(如 Agent
或 ets
或其他)并直接从 [=12] 存储值=]秒。这个解决方案有一个明显的缺点:它的工作流程是不确定的,人们可能不会假设所有 10 个响应在任何时候都被 处理和存储 。也就是说,在某些情况下 cast
s 甚至可能会丢失和未处理,您没有机会收到有关这方面的通知。没遇到过这种情况,不过也算是合法了。
因此,在这种特殊情况下,您可能应该只使用 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 个 GenServer
s 的原因是什么,为什么不使用命名 GenServer
s 来不打扰 pid
s,但这显然超出了这里的范围.