我正在寻找使用 gen_server:cast/2 处理Erlang异步消息的好例子。
我在OTP ssh模块中看到过一个例子,它通过Module:handle_cast/2接收请求,将其保存在模块的本地队列中,稍后通过显式发送消息发送回与请求对应的回复消息给来电者。当我试图阅读它时,我几乎无法跟踪代码,也无法掌握这个想法。
一段伪代码表示赞赏。
我正在寻找使用 gen_server:cast/2 处理Erlang异步消息的好例子。
我在OTP ssh模块中看到过一个例子,它通过Module:handle_cast/2接收请求,将其保存在模块的本地队列中,稍后通过显式发送消息发送回与请求对应的回复消息给来电者。当我试图阅读它时,我几乎无法跟踪代码,也无法掌握这个想法。
一段伪代码表示赞赏。
我相信您指的是ssh_connection_manager模块。
当您执行 agen_server:cast/2
时,请求将在Module:handle_cast/2
函数中处理。这里有几点需要注意:
handle_cast
参数中,您没有关于发件人的信息,因此您不能 - 除非您在消息本身中发送此信息 - 将一些结果发回给它。gen_server:cast/2
,不会等待回复。实际上,它甚至不关心消息是否到达(有一些例外)。handle_cast/2
中,您可以只返回一个noreply或一个停止元组,因此无法在那里返回回复。也就是说,您一直在查看的代码背后的想法应该是(简化事情):
gen_server:call/2
此时,您有两种可能性,具体取决于您是否需要更多信息来计算来自其他客户端 (A) 或来自同一客户端 (B) 的结果:
gen_server:call/2
.通常,您在发送演员表时不会期望直接回复,否则您将使用 gen_server:call。
一个真实的例子,我有一个 gen_server 处理一些“通道”,并且有很多用途可以将通道名称附加到错误日志中。通道名称存储在 gen_server 的状态中。为了不阻止想要记录错误的进程,我不使用“获取名称”同步调用来获取名称作为前缀,而是使用强制类型转换发送消息:
error(Pid, Tags) ->
gen_server:cast(Pid, {log, error_report, Tags}).
warning(Pid, Tags) ->
gen_server:cast(Pid, {log, warning_report, Tags}).
info(Pid, Tags) ->
gen_server:cast(Pid, {log, info_report, Tags}).
演员表在一个非常简单的处理程序中处理,不会返回。
handle_cast({log, Report, Tags}, #state{name=Name}=State) ->
error_logger:Report([{chan, Name} | Tags]),
{noreply, State};
如果您有异步消息要发回,这完全独立于演员表的处理。您不知何故需要知道将这些消息发送到哪里,您必须以State
某种方式存储这些消息,或者您使用的是固定名称。
通常,您不应该只发送消息,而是调用接收进程模块的函数(这可能是另一个强制转换或普通消息发送)。