【问题标题】:How to catch GenServer.call(destination, ...) failure when destination process doesn't exist当目标进程不存在时如何捕获 GenServer.call(destination, ...) 失败
【发布时间】:2020-09-06 14:40:34
【问题描述】:

在我的应用程序中,所有登录的用户都由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 不再存在,例如,因为用户已经不活动一段时间并且进程已被清除(会话已过期)或因为部分此时无法访问集群的一部分(目前的虚构用例)。在这些情况下,调用GenServer.call(via_tuple(id), {:the_action, params}) 会导致下面的错误,这也会导致HTTP 端点进程(下面的#PID<0.1359.0>)崩溃,进而导致500 HTTP 错误(dump api 调用,嗯,转储状态用于调试目的的进程):

[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 returned pid`,或者如果找不到进程,则向控制器返回错误。

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

【问题讨论】:

    标签: elixir


    【解决方案1】:

    这就是GenServer.call/3 handles errors 中的方式。它仍然调用whereis/1,因此您可以自己调用whereis/1,或者从我链接的代码中复制逻辑,或者使用Kernel.SpecialForms.try/1catch 异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多