假设我有一个简单的genserver,它具有一个简单的:queue状态。使用handle_cast不断添加项目。每隔5秒钟,我使用Process.send_after处理队列。该调用通过返回具有当前状态的handle_info来处理。队列将被处理并清空,然后将新的空队列用作genserver的当前状态。
我的问题是这样的:
当队列正在处理时,呼叫进入genserver会发生什么?由于我将新的空队列返回到handle_info {:noreply,:queue.new},是否可以覆盖在我处理队列时添加的项目?还是将genserver强制转换为自己排队,然后在handle_info完成后允许其完成?
基本上,我担心handle_info期间缺少项目。
代码:
defmodule TcpClient.Queue do
use GenServer
require Logger
def start_link do
queue = :queue.new()
GenServer.start_link(__MODULE__, queue, name: {:global, :tcp_queue})
end
def init(queue) do
Logger.debug("Starting up Queue")
schedule_work()
{:ok, queue}
end
def enqueue(msg) do
Logger.debug("Item Added")
GenServer.cast(whereis(), {:enqueue, msg})
end
defp schedule_work() do
Process.send_after(self(), :work, 1 * 1 * 300)
end
def handle_cast({:enqueue, msg}, state) do
{:noreply, :queue.in(msg, state)}
end
def handle_info(:work, queue) do
case :queue.is_empty(queue) do
true ->
Logger.debug("No items to Process")
nil
false ->
Logger.debug("Processing Queue")
:queue.to_list(queue)
|> Enum.map(&TcpClient.Repo.add_message(&1))
queue = :queue.new()
end
schedule_work()
{:noreply, queue}
end
def whereis() do
:global.whereis_name(:tcp_queue)
end
end
答案 0 :(得分:1)
传入的邮件将被放入进程邮箱,并且不会被处理,直到进程从先前的handle_***
返回。您冒着使进程的邮箱溢出的风险,而不会错过某些消息。
为防止这种情况,GenStage
由Elixir Core团队明确创建以反击压力。