我试图通过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
发件人/来电者模块
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
答案 0 :(得分:2)
尽管
GenServer.cast/2
[...]我如何收集回复
你本身不能。转换请求是异步的,并返回无响应。从cast
收集数据的唯一方法是引入商店(如Agent
或ets
或其他),并直接存储{{1 }}秒。这个解决方案有一个明显的缺点:它的工作流程将不确定,人们可能不会假设所有10个响应都在任何时候处理和存储。也就是说,cast
在某些情况下甚至可能会丢失和未经处理,您也没有机会得到通知。我从来没有见过这样的案子,但它被认为是合法的。
因此,在这种特殊情况下,您可能只需使用GenServer.call/2
代替cast
,并使用Enum.map/2
直接在迭代中收集回复:
cast
结果你将有10个元组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}
的原因是什么,为什么不使用命名的GenServer
来打扰GenServer
s,但这显然超出了范围