GenStage:在GenServer更新时重试handle_demand

时间:2017-09-28 02:02:10

标签: elixir phoenix-framework gen-server genstage

如果我的GenStage的handle_demand/2方法如下所示:

def handle_demand(demand, _state) when demand > 0 do
  case Queue.dequeue do
    nil ->
      Logger.debug("Queue empty.")
      {:noreply, [], []}
    {job, updated_queue} -> {:noreply, job, updated_queue}
  end
end

如何让它重新运行"重新运行"当我的Queue(GenServer)被更改/更新时?

我的队列模块看起来像这样:

defmodule Queue do
  use GenServer

  ### client

  def start_link(state \\ []) do
    GenServer.start_link(__MODULE__, state, name: __MODULE__)
  end

  def queue, do: GenServer.call(__MODULE__, :queue)

  def enqueue(value), do: GenServer.cast(__MODULE__, {:enqueue, value})

  def dequeue, do: GenServer.call(__MODULE__, :dequeue)

  ### server

  def init(state), do: {:ok, state}

  def handle_call(:dequeue, _from, [value | state]) do
    {:reply, value, state}
  end

  def handle_call(:dequeue, _from, []), do: {:reply, nil, []}

  def handle_call(:queue, _from, state), do: {:reply, state, state}

  def handle_cast({:enqueue, value}, state) do
    {:noreply, state ++ [value]}
  end
end

1 个答案:

答案 0 :(得分:1)

为什么要在Queue更改时“重新运行”它?这是对GenStage的严重滥用。它的发明是为了让背压,来自 Queue,反之亦然。在现实生活中,您根本不需要GenStage,或者您不希望在Queue更新时“重新运行”需求,因为它迟早会通过超时/消息框将其删除

当它处理队列中的先前加载时,你可能有一个“消费者”来调用handle_demandGenStage的回购邮件four incredibly clear examples使用不同的模式与GenStage一起使用。除此之外,Elixir blog中的GenStage还有一个很好的介绍。

只需选择您需要的模式,并从上面链接的来源中采用它。