我有一个Phoenix应用程序,HTTP端点后面有复杂的业务逻辑。此逻辑包括与数据库和一些外部服务的交互,一旦请求处理开始,就不能中断,直到所有操作都完成。
但如果客户端突然关闭连接,Cowboy或Ranch似乎会杀死请求处理程序进程(Phoenix控制器),这会导致业务流程部分执行。为了调试此问题,我在控制器操作中编写了以下代码:
Process.flag(:trap_exit, true)
receive do
msg -> Logger.info("Message: #{inspect msg}")
after
10_000 -> Logger.info("Timeout")
end
并为模拟连接关闭我设置超时:curl --request POST 'http://localhost:4003' --max-time 3
。3秒后,在IEx控制台中,我看到进程即将退出:Message: {:EXIT, #PID<0.4196.0>, :shutdown}
.
所以我需要让控制器完成它的工作,并回复客户端,如果它还在那里,或什么都不做,如果连接丢失。这将是实现这一点的最佳方式:
- 在控制器操作中捕获退出并忽略退出消息;
- 在控制器动作中产生未链接
Task
并等待其结果; - 以某种方式配置牛仔/牧场,使它不会杀死处理程序进程,如果可能的话(尝试了
exit_on_close
,但没有运气)?
1条答案
按热度按时间cdmah0mi1#
处理进程将在请求结束后被终止,这是它们的目的。如果你想在后台处理一些数据,那么启动额外的进程。最简单的方法是你提出的第二种方法,但使用
Task.Supervisor
略有修改。因此,在应用程序管理器中,您可以使用所选的名称启动
Task.Supervisor
:然后在请求处理程序中:
这样您就不需要担心用户不再接收消息时处理情况