繁体   English   中英

在handle_info或handle_call期间Genserver状态更改

[英]Genserver state change during handle_info or handle_call

假设我有一个简单的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

传入邮件被投入过程邮箱,不会被处理 ,直到该进程已经从以前返回handle_*** 您冒着使进程的邮箱溢出的风险,不要错过某些消息。

为了防止这种情况, GenStage由Elixir Core团队明确创建,以反击压力。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM