当目标进程不存在时,如何捕获GenServer.call(destination,...)失败



在我的应用程序中,所有记录的用户都由一个GenServer表示,我称之为UserAgent,它基本上将每个用户的状态保存在内存中。所有这些进程都在集群中注册在一个基于Horde的分布式注册表中,该注册表具有唯一的ID。每当用户执行某个操作时,客户端应用程序都会将要执行的操作与user_id一起发送。在服务器端,控制器检查参数(强制、可选、语法等(,并最终调用UserAgent.the_action(user_id, other_params)the_action(...)函数只是向服务器发送一条消息,其中包含要执行的操作:GenServer.call(via_tuple(id), {:the_action, params})

在某些情况下,user_id引用的UserAgent不再存在,例如,因为用户已处于非活动状态一段时间,进程已被清除(sesion已过期(,或者因为此时无法访问集群的某些部分(目前是虚构的用例(。在这些情况下,调用GenServer.call(via_tuple(id), {:the_action, params})会导致下面的错误,该错误还会使HTTP端点进程(下面的#PID<0.1359.0>(崩溃,进而导致500HTTP错误(dumpAPI调用会出于调试目的转储进程的状态(:

[error] #PID<0.1359.0> running AppWeb.Endpoint (connection #PID<0.1358.0>, stream id 1) terminated
Server: localhost:4001 (http)
Request: GET /api/v1/dump/5f534b99d6ca3fe1ff6d2f78
** (exit) exited in: GenServer.call({:via, Horde.Registry, {App.DReg, "5f534b99d6ca3fe1ff6d2f78"}}, :dump, 5000)
** (EXIT) no process: the process is not alive or there's no process currently associated 
with the given name, possibly because its application isn't started

我只是不知道如何拦截这个错误。实际上,我最终在UserAgent的客户端部分调用Horde.Registry.lookup(App.UserAgent.via_tuple(user_id)),然后调用GenServer.call() with the returnedpid,或者如果找不到进程,则向控制器返回错误。

我想知道是否有更好的方法。

这就是GenServer.call/3如何处理elixir中的错误。尽管如此,它还是调用whereis/1,所以您可以自己调用whereis/1,或者复制我链接的代码中的逻辑,或者使用Kernel.SpecialForms.try/1catch作为异常。

最新更新