- Restored original PacketConsumer implementation from before optimizations - Reverted to fixed batch size of 50 packets (original value) - Removed SystemMonitor and InsertOptimizer from application startup - Restored original config with buffer size 1000 and batch timeout 1000ms - Removed all dynamic batch sizing and optimization logic The recent performance optimizations were causing packet buffer overflows because the dynamic batch sizing was actually slowing down processing. Reverting to the simpler, working implementation that processes packets consistently without buffer overflows. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
56 lines
1.7 KiB
Elixir
56 lines
1.7 KiB
Elixir
defmodule Aprsme.PacketProducer do
|
|
@moduledoc """
|
|
GenStage producer that handles incoming APRS packets and sends them to consumers
|
|
for efficient batch processing.
|
|
"""
|
|
use GenStage
|
|
|
|
require Logger
|
|
|
|
def start_link(opts \\ []) do
|
|
GenStage.start_link(__MODULE__, opts, name: __MODULE__)
|
|
end
|
|
|
|
def submit_packet(packet_data) do
|
|
GenStage.cast(__MODULE__, {:packet, packet_data})
|
|
end
|
|
|
|
@impl true
|
|
def init(opts) do
|
|
{:producer, %{demand: 0, buffer: [], max_buffer_size: opts[:max_buffer_size] || 1000}}
|
|
end
|
|
|
|
@impl true
|
|
def handle_demand(incoming_demand, %{demand: demand, buffer: buffer} = state) do
|
|
{events, remaining_buffer, remaining_demand} = dispatch_events(buffer, demand + incoming_demand)
|
|
{:noreply, events, %{state | demand: remaining_demand, buffer: remaining_buffer}}
|
|
end
|
|
|
|
@impl true
|
|
def handle_cast({:packet, packet_data}, %{demand: demand, buffer: buffer, max_buffer_size: max_size} = state) do
|
|
if demand > 0 do
|
|
# We have demand, send immediately
|
|
{:noreply, [packet_data], %{state | demand: demand - 1}}
|
|
else
|
|
# No demand, buffer the packet
|
|
new_buffer = [packet_data | buffer]
|
|
|
|
if length(new_buffer) > max_size do
|
|
# Buffer is full, drop oldest packet
|
|
Logger.warning("Packet buffer full, dropping oldest packet")
|
|
{:noreply, [], %{state | buffer: Enum.take(new_buffer, max_size)}}
|
|
else
|
|
{:noreply, [], %{state | buffer: new_buffer}}
|
|
end
|
|
end
|
|
end
|
|
|
|
defp dispatch_events(buffer, demand) when demand > 0 and length(buffer) > 0 do
|
|
{events, remaining} = Enum.split(buffer, demand)
|
|
{events, remaining, demand - length(events)}
|
|
end
|
|
|
|
defp dispatch_events(buffer, demand) do
|
|
{[], buffer, demand}
|
|
end
|
|
end
|