I am testing the following pattern in a GenServer:
def handle_info({:tcp, _, data}, s) do
# IO.puts "\nrx: \n#{Base.encode16(data)}\n"
extra = _proc_data(<<s.extra::binary, data::binary>>)
:inet.setopts(s.socket, active: :once)
{:noreply, %{s | extra: extra}}
end
There is a problem when data comes in fast, and i'm unable to update state before :inet.setopts(s.socket, active: :once)
releases new data
Must {:noreply, %{s | extra: extra}}
be the last line for handle_info
, or can I perform the :inet.setopts(s.socket, active: :once)
last?
Is there a better way to do this?
One technique I've used in the past is to send the data to another GenServer
for processing. This would allow the current process to call :inet.setopts(s.socket, active: :once)
faster.
def handle_info({:tcp, _, data}, s) do
# IO.puts "\nrx: \n#{Base.encode16(data)}\n"
GenServer.cast(s.processor, {:data, data})
:inet.setopts(s.socket, active: :once)
{:noreply, s}
end
Processor:
defmodule DataProcessor do
use GenServer
def start_link(opts), do: GenServer.start_link(__MODULE__, [], opts)
def init(_), do: {:ok, %{}}
def handle_cast({:data, data}, state) do
extra = _proc_data(s.extra <> data)
{:noreply, %{state| extra: extra}}
end
defp _proc_data(data) do
...
end
end