Elixir 如何在GenServer中获取异步失败的通知?
在elixirElixir 如何在GenServer中获取异步失败的通知?,elixir,gen-server,Elixir,Gen Server,在elixirGenServer中,有同步和异步方法、handle\u cast和handle\u call。在异步情况下,如果方法失败,我如何获得通知 方法失败意味着在handle\u调用方法中,我需要定义一些逻辑来查询/写入数据库。如果数据库操作失败,我需要通知调用方此失败。在异步方法中,我如何才能做到这一点呢?因此,鼓励您“任其自然”的评论通常是正确的。惯用的Erlang和Elixir要求“快速失败”,并允许主管重新启动崩溃的组件 也就是说,有时撞车是不合适的;通常情况下,当你知道负面结果
GenServer
中,有同步和异步方法、handle\u cast
和handle\u call
。在异步情况下,如果方法失败,我如何获得通知
方法失败意味着在
handle\u调用
方法中,我需要定义一些逻辑来查询/写入数据库。如果数据库操作失败,我需要通知调用方此失败。在异步方法中,我如何才能做到这一点呢?因此,鼓励您“任其自然”的评论通常是正确的。惯用的Erlang和Elixir要求“快速失败”,并允许主管重新启动崩溃的组件
也就是说,有时撞车是不合适的;通常情况下,当你知道负面结果可能发生时。标准库中的许多API通过返回结果元组来处理此问题,即{:ok,result}
或{:error,reason}
,并使调用代码负责崩溃或尝试其他操作
在您的用例中,我认为您应该使用数据从进程调用数据库写/查询代码,而不使用异步方法,首先修复数据库性能。如果这确实是一个长期运行的查询,并且优化数据库不是正确的答案,那么您的下一个最佳选择是任务模块(),它是Elixir标准库的一部分-它为异步任务执行提供了内置功能
我知道人们不回答你的问题是多么令人沮丧,所以我会回答;但请注意,这几乎肯定不是解决原始问题的正确方法
关键的细节是将调用进程的pid传递给工作进程,以便它可以稍后发送结果消息:
defmodule CastBackExampleWorker do
use GenServer
# ...
def do_operation(args) do
caller = self()
ref = make_ref()
# Pass the caller's pid to the GenServer so that it can message back later
GenServer.cast(__MODULE__, {:do_operation, caller, ref, args})
# hand back a unique ref for this request
ref
end
# ...
def handle_cast({:do_operation, caller, ref, args}, state) do
case execute_operation(args) do
{:ok, result} -> send(caller, {__MODULE__, ref, {:ok, result}})
{:error, reason} -> send(caller, {__MODULE__, ref, {:error, reason}})
end
{:noreply, state}
end
end
defmodule CastBackExampleClient do
use GenServer
# ...
def handle_call(:my_real_work, _from, state) do
# ignoring the ref, but we could stick it into our state for later...
_ref = CastBackExampleWorker.do_operation([])
{:reply, :ok, state}
end
def handle_info({CastBackExampleWorker, _ref, outcome}, state) do
# Do something with the outcome here
{:noreply, state}
end
end
有没有办法检查该流程的PID?也许这是一个解决办法。我不太清楚你所说的“当方法失败时”是什么意思。您是否正在考虑导致整个GenServer崩溃的故障情况?恐怕你需要更具体一点。@PawełDawczak谢谢,我已经更新了我的问题。让它消失吧。DB故障是导致死亡的合理原因。如何在异步函数中捕获此故障?