change packet retention to a year
This commit is contained in:
parent
b6260a950f
commit
2b3cc3f75e
6 changed files with 84 additions and 99 deletions
|
|
@ -38,25 +38,6 @@ defmodule Aprs.Is do
|
||||||
last_second_timestamp: System.system_time(:second)
|
last_second_timestamp: System.system_time(:second)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Set up ets tables
|
|
||||||
|
|
||||||
# with {:ok, :aprs} <- :ets.file2tab(:erlang.binary_to_list("priv/aprs.ets")),
|
|
||||||
# {:ok, :aprs_messages} <- :ets.file2tab(:erlang.binary_to_list("priv/aprs_messages.ets")) do
|
|
||||||
# else
|
|
||||||
# {:error, _reason} ->
|
|
||||||
# Logger.debug("Ets files not found. Creating new ETS tables.")
|
|
||||||
# # Create new ETS tables
|
|
||||||
# :ets.new(:aprs, [:set, :protected, :named_table])
|
|
||||||
# :ets.new(:aprs_messages, [:bag, :protected, :named_table])
|
|
||||||
|
|
||||||
# # Write them to file here in case genserver is brutally terminated
|
|
||||||
# :ets.tab2file(:aprs, :erlang.binary_to_list("priv/aprs.ets"))
|
|
||||||
# :ets.tab2file(:aprs_messages, :erlang.binary_to_list("priv/aprs_messages.ets"))
|
|
||||||
|
|
||||||
# _ ->
|
|
||||||
# Logger.error("Unable to set up ETS tables for message storage.")
|
|
||||||
# end
|
|
||||||
|
|
||||||
with {:ok, socket} <- connect_to_aprs_is(server, port),
|
with {:ok, socket} <- connect_to_aprs_is(server, port),
|
||||||
:ok <- send_login_string(socket, aprs_user_id, aprs_passcode, default_filter) do
|
:ok <- send_login_string(socket, aprs_user_id, aprs_passcode, default_filter) do
|
||||||
timer = create_timer(@aprs_timeout)
|
timer = create_timer(@aprs_timeout)
|
||||||
|
|
|
||||||
|
|
@ -270,11 +270,11 @@ defmodule Aprs.Packets do
|
||||||
Configure packet retention policy.
|
Configure packet retention policy.
|
||||||
|
|
||||||
Packets are retained based on these rules:
|
Packets are retained based on these rules:
|
||||||
- Default retention is 30 days (configurable via :packet_retention_days)
|
- Default retention is 365 days (1 year) (configurable via :packet_retention_days)
|
||||||
- Returns the number of packets deleted
|
- Returns the number of packets deleted
|
||||||
"""
|
"""
|
||||||
def clean_old_packets do
|
def clean_old_packets do
|
||||||
retention_days = Application.get_env(:aprs, :packet_retention_days, 30)
|
retention_days = Application.get_env(:aprs, :packet_retention_days, 365)
|
||||||
cutoff_time = DateTime.add(DateTime.utc_now(), -retention_days * 86_400, :second)
|
cutoff_time = DateTime.add(DateTime.utc_now(), -retention_days * 86_400, :second)
|
||||||
|
|
||||||
{deleted_count, _} = Repo.delete_all(from(p in Packet, where: p.received_at < ^cutoff_time))
|
{deleted_count, _} = Repo.delete_all(from(p in Packet, where: p.received_at < ^cutoff_time))
|
||||||
|
|
@ -282,6 +282,26 @@ defmodule Aprs.Packets do
|
||||||
deleted_count
|
deleted_count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Clean packets older than a specific number of days.
|
||||||
|
|
||||||
|
This function allows for more granular cleanup operations by specifying
|
||||||
|
the exact age threshold for packet deletion.
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
- `days` - Number of days to retain packets (packets older than this will be deleted)
|
||||||
|
|
||||||
|
## Returns
|
||||||
|
- Number of packets deleted
|
||||||
|
"""
|
||||||
|
def clean_packets_older_than(days) when is_integer(days) and days > 0 do
|
||||||
|
cutoff_time = DateTime.add(DateTime.utc_now(), -days * 86_400, :second)
|
||||||
|
|
||||||
|
{deleted_count, _} = Repo.delete_all(from(p in Packet, where: p.received_at < ^cutoff_time))
|
||||||
|
|
||||||
|
deleted_count
|
||||||
|
end
|
||||||
|
|
||||||
# Helper to convert various types to float
|
# Helper to convert various types to float
|
||||||
defp to_float(value) when is_float(value), do: value
|
defp to_float(value) when is_float(value), do: value
|
||||||
defp to_float(value) when is_integer(value), do: value * 1.0
|
defp to_float(value) when is_integer(value), do: value * 1.0
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ defmodule Aprs.Passcode do
|
||||||
hash =
|
hash =
|
||||||
Enum.reduce(0..div(length(chars) - 1, 2), hash, fn i, acc ->
|
Enum.reduce(0..div(length(chars) - 1, 2), hash, fn i, acc ->
|
||||||
current_char = Enum.at(chars, i * 2)
|
current_char = Enum.at(chars, i * 2)
|
||||||
next_char = if i * 2 + 1 < length(chars), do: Enum.at(chars, i * 2 + 1), else: nil
|
next_char = if i * 2 + 1 < length(chars), do: Enum.at(chars, i * 2 + 1)
|
||||||
step1 = Bitwise.bxor(acc, Bitwise.bsl(current_char, 8))
|
step1 = Bitwise.bxor(acc, Bitwise.bsl(current_char, 8))
|
||||||
|
|
||||||
step2 =
|
step2 =
|
||||||
|
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
defmodule Aprs.Scheduled.PacketCleanup do
|
|
||||||
@moduledoc """
|
|
||||||
Scheduled task to clean up old APRS packet data.
|
|
||||||
|
|
||||||
This module is responsible for:
|
|
||||||
1. Removing packets older than the retention period (30 days by default)
|
|
||||||
2. Logging statistics about the cleanup operation
|
|
||||||
"""
|
|
||||||
|
|
||||||
use GenServer
|
|
||||||
|
|
||||||
alias Aprs.Packets
|
|
||||||
|
|
||||||
require Logger
|
|
||||||
|
|
||||||
# Run cleanup once per day
|
|
||||||
@cleanup_interval_ms 24 * 60 * 60 * 1000
|
|
||||||
|
|
||||||
def start_link(_opts) do
|
|
||||||
GenServer.start_link(__MODULE__, %{})
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def init(state) do
|
|
||||||
# Schedule first cleanup
|
|
||||||
schedule_cleanup()
|
|
||||||
{:ok, state}
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def handle_info(:cleanup, state) do
|
|
||||||
# Run the cleanup
|
|
||||||
_cleanup_count = perform_cleanup()
|
|
||||||
|
|
||||||
# Schedule next cleanup
|
|
||||||
schedule_cleanup()
|
|
||||||
|
|
||||||
{:noreply, state}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp perform_cleanup do
|
|
||||||
Logger.info("Starting scheduled APRS packet cleanup")
|
|
||||||
|
|
||||||
# Count packets before cleanup for statistics
|
|
||||||
_total_before = count_total_packets()
|
|
||||||
|
|
||||||
# Perform the cleanup
|
|
||||||
deleted_count = Packets.clean_old_packets()
|
|
||||||
|
|
||||||
# Log results
|
|
||||||
retention_days = Application.get_env(:aprs, :packet_retention_days, 30)
|
|
||||||
Logger.info("APRS packet cleanup complete: removed #{deleted_count} packets older than #{retention_days} days")
|
|
||||||
|
|
||||||
# Return deleted count
|
|
||||||
deleted_count
|
|
||||||
end
|
|
||||||
|
|
||||||
defp count_total_packets do
|
|
||||||
# Import modules needed for database operations
|
|
||||||
|
|
||||||
Aprs.Repo.aggregate(Aprs.Packet, :count, :id)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp schedule_cleanup do
|
|
||||||
# Schedule next cleanup
|
|
||||||
Process.send_after(self(), :cleanup, @cleanup_interval_ms)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -3,9 +3,16 @@ defmodule Aprs.Workers.PacketCleanupWorker do
|
||||||
Oban worker for cleaning up old APRS packet data.
|
Oban worker for cleaning up old APRS packet data.
|
||||||
|
|
||||||
This worker is responsible for:
|
This worker is responsible for:
|
||||||
1. Removing packets older than the retention period (30 days by default)
|
1. Removing packets older than the retention period (1 year by default)
|
||||||
2. Removing old packets from the displayed map (older than 1 hour)
|
2. Providing granular cleanup with custom age parameters
|
||||||
3. Logging statistics about the cleanup operation
|
3. Logging statistics about cleanup operations
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
- `perform/1` - Standard cleanup using configured retention period
|
||||||
|
- `cleanup_packets_older_than/1` - Cleanup packets older than specified days
|
||||||
|
- `schedule_cleanup/0` - Schedule standard cleanup job
|
||||||
|
- `schedule_cleanup_for_age/1` - Schedule cleanup with custom age parameter
|
||||||
|
- `schedule_daily_cleanup/0` - Schedule daily cleanup at midnight UTC
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Oban.Worker, queue: :maintenance, max_attempts: 3
|
use Oban.Worker, queue: :maintenance, max_attempts: 3
|
||||||
|
|
@ -19,17 +26,33 @@ defmodule Aprs.Workers.PacketCleanupWorker do
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
@impl Oban.Worker
|
@impl Oban.Worker
|
||||||
|
def perform(%Oban.Job{args: %{"cleanup_days" => days}}) when is_integer(days) do
|
||||||
|
Logger.info("Starting scheduled APRS packet cleanup for packets older than #{days} days")
|
||||||
|
|
||||||
|
# Count packets before cleanup for statistics
|
||||||
|
_total_before = count_total_packets()
|
||||||
|
|
||||||
|
# Perform the cleanup of old packets with custom age
|
||||||
|
deleted_count = Packets.clean_packets_older_than(days)
|
||||||
|
|
||||||
|
# Log results
|
||||||
|
Logger.info("APRS packet cleanup complete: removed #{deleted_count} packets older than #{days} days")
|
||||||
|
|
||||||
|
# Return success
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
def perform(%Oban.Job{args: _args}) do
|
def perform(%Oban.Job{args: _args}) do
|
||||||
Logger.info("Starting scheduled APRS packet cleanup")
|
Logger.info("Starting scheduled APRS packet cleanup")
|
||||||
|
|
||||||
# Count packets before cleanup for statistics
|
# Count packets before cleanup for statistics
|
||||||
_total_before = count_total_packets()
|
_total_before = count_total_packets()
|
||||||
|
|
||||||
# Perform the cleanup of old packets (older than 30 days)
|
# Perform the cleanup of old packets (older than 1 year by default)
|
||||||
deleted_count = cleanup_old_packets()
|
deleted_count = cleanup_old_packets()
|
||||||
|
|
||||||
# Log results
|
# Log results
|
||||||
retention_days = Application.get_env(:aprs, :packet_retention_days, 30)
|
retention_days = Application.get_env(:aprs, :packet_retention_days, 365)
|
||||||
Logger.info("APRS packet cleanup complete: removed #{deleted_count} packets older than #{retention_days} days")
|
Logger.info("APRS packet cleanup complete: removed #{deleted_count} packets older than #{retention_days} days")
|
||||||
|
|
||||||
# Return success
|
# Return success
|
||||||
|
|
@ -43,6 +66,13 @@ defmodule Aprs.Workers.PacketCleanupWorker do
|
||||||
|> Oban.insert()
|
|> Oban.insert()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Schedule cleanup with custom age parameter
|
||||||
|
def schedule_cleanup_for_age(days) when is_integer(days) and days > 0 do
|
||||||
|
%{"cleanup_days" => days}
|
||||||
|
|> Oban.Job.new(worker: __MODULE__, queue: :maintenance)
|
||||||
|
|> Oban.insert()
|
||||||
|
end
|
||||||
|
|
||||||
# Schedule this job to run daily at midnight UTC
|
# Schedule this job to run daily at midnight UTC
|
||||||
def schedule_daily_cleanup do
|
def schedule_daily_cleanup do
|
||||||
# Calculate when the next midnight UTC is
|
# Calculate when the next midnight UTC is
|
||||||
|
|
@ -74,4 +104,25 @@ defmodule Aprs.Workers.PacketCleanupWorker do
|
||||||
# Use the existing function from Packets context
|
# Use the existing function from Packets context
|
||||||
Packets.clean_old_packets()
|
Packets.clean_old_packets()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Perform cleanup of packets older than a specific number of days.
|
||||||
|
|
||||||
|
This function provides more granular control over packet cleanup operations.
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
- `days` - Number of days to retain packets (packets older than this will be deleted)
|
||||||
|
|
||||||
|
## Returns
|
||||||
|
- Number of packets deleted
|
||||||
|
"""
|
||||||
|
def cleanup_packets_older_than(days) when is_integer(days) and days > 0 do
|
||||||
|
Logger.info("Starting APRS packet cleanup for packets older than #{days} days")
|
||||||
|
|
||||||
|
deleted_count = Packets.clean_packets_older_than(days)
|
||||||
|
|
||||||
|
Logger.info("APRS packet cleanup complete: removed #{deleted_count} packets older than #{days} days")
|
||||||
|
|
||||||
|
deleted_count
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,23 @@
|
||||||
defmodule Aprs.PasscodeTest do
|
defmodule Aprs.PasscodeTest do
|
||||||
use ExUnit.Case
|
use ExUnit.Case
|
||||||
|
|
||||||
doctest Aprs.Passcode
|
doctest Aprs.Passcode
|
||||||
|
|
||||||
describe "generate/1" do
|
describe "generate/1" do
|
||||||
test "generates correct passcode for W5ISP" do
|
test "generates correct passcode for W5ISP" do
|
||||||
assert Aprs.Passcode.generate("W5ISP") == 15748
|
assert Aprs.Passcode.generate("W5ISP") == 15_748
|
||||||
end
|
end
|
||||||
|
|
||||||
test "handles callsigns with SSIDs" do
|
test "handles callsigns with SSIDs" do
|
||||||
assert Aprs.Passcode.generate("W5ISP-1") == 15748
|
assert Aprs.Passcode.generate("W5ISP-1") == 15_748
|
||||||
end
|
end
|
||||||
|
|
||||||
test "handles lowercase callsigns" do
|
test "handles lowercase callsigns" do
|
||||||
assert Aprs.Passcode.generate("w5isp") == 15748
|
assert Aprs.Passcode.generate("w5isp") == 15_748
|
||||||
end
|
end
|
||||||
|
|
||||||
test "handles long callsigns" do
|
test "handles long callsigns" do
|
||||||
assert Aprs.Passcode.generate("W5ISP-LONG") == 15748
|
assert Aprs.Passcode.generate("W5ISP-LONG") == 15_748
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue