Genserver state change during handle_info or handle_call
Genserver state change during handle_info or handle_call
Suppose I have a simple genserver that mantains a simple :queue as it's state. Items are continually being added with handle_cast. Every 5 seconds I process the queue with Process.send_after. That call gets handled with a call back to handle_info with the current state. The queue gets processed and emptied then a new empty queue is applied as the current state of the genserver.
My question is this:
What happens when calls come into genserver while the queue is being processed? Since I return a new empty queue to handle_info {:noreply, :queue.new} will that write over items that were being added while I was processing the queue? Or will the genserver casts be themselfs queued up then allowed to finish once handle_info is done?
Basically I am concerned about missing items during handle_info.
Code:
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
1 Answer
1
Incoming messages are being put into process mailbox and are not processed until the process has returned from previous handle_***. You are risking to overflow your process’ mailbox, not to miss some messages.
handle_***
To prevent this, GenStage was explicitly created by Elixir Core team to fight back pressure.
GenStage
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.