Fix packet counter accuracy after TRUNCATE operations
The packet counter uses a PostgreSQL sequence that doesn't get reset when the packets table is truncated, causing inaccurate counts. This migration: - Creates an event trigger that automatically resets the packet counter sequence when the packets table is truncated - Adds a manual reset function reset_packet_counter() that can be called if needed - Improves the get_packet_count() function to properly handle when the sequence is at 0 After applying this migration, the counter will automatically reset to 0 whenever TRUNCATE is used on the packets table. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
2bdad557e9
commit
2629589b7f
1 changed files with 113 additions and 0 deletions
|
|
@ -0,0 +1,113 @@
|
|||
defmodule Aprsme.Repo.Migrations.AddTruncateResetForPacketCounter do
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
# Create a function to reset the packet counter sequence
|
||||
execute """
|
||||
CREATE OR REPLACE FUNCTION reset_packet_counter_on_truncate()
|
||||
RETURNS event_trigger AS $$
|
||||
DECLARE
|
||||
cmd RECORD;
|
||||
BEGIN
|
||||
FOR cmd IN SELECT * FROM pg_event_trigger_ddl_commands()
|
||||
LOOP
|
||||
IF cmd.command_tag = 'TRUNCATE TABLE' AND cmd.object_identity = 'public.packets' THEN
|
||||
-- Reset the sequence to 0
|
||||
PERFORM setval('packet_count_seq', 0, false);
|
||||
|
||||
-- Also update the deprecated packet_counters table for backward compatibility
|
||||
UPDATE packet_counters
|
||||
SET count = 0, updated_at = NOW()
|
||||
WHERE counter_type = 'total_packets';
|
||||
END IF;
|
||||
END LOOP;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
"""
|
||||
|
||||
# Create an event trigger for TRUNCATE operations
|
||||
execute """
|
||||
CREATE EVENT TRIGGER reset_packet_counter_trigger
|
||||
ON ddl_command_end
|
||||
WHEN TAG IN ('TRUNCATE TABLE')
|
||||
EXECUTE FUNCTION reset_packet_counter_on_truncate();
|
||||
"""
|
||||
|
||||
# Also create a manual reset function that can be called if needed
|
||||
execute """
|
||||
CREATE OR REPLACE FUNCTION reset_packet_counter()
|
||||
RETURNS void AS $$
|
||||
BEGIN
|
||||
-- Reset the sequence
|
||||
PERFORM setval('packet_count_seq', 0, false);
|
||||
|
||||
-- Update the deprecated table
|
||||
UPDATE packet_counters
|
||||
SET count = 0, updated_at = NOW()
|
||||
WHERE counter_type = 'total_packets';
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
"""
|
||||
|
||||
# Fix the get_packet_count function to handle the case when sequence is at 0
|
||||
execute """
|
||||
CREATE OR REPLACE FUNCTION get_packet_count()
|
||||
RETURNS BIGINT AS $$
|
||||
DECLARE
|
||||
seq_exists BOOLEAN;
|
||||
current_val BIGINT;
|
||||
BEGIN
|
||||
-- Check if sequence exists
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM pg_sequences
|
||||
WHERE schemaname = 'public' AND sequencename = 'packet_count_seq'
|
||||
) INTO seq_exists;
|
||||
|
||||
IF NOT seq_exists THEN
|
||||
-- Fallback to counting if sequence doesn't exist
|
||||
RETURN (SELECT COUNT(*) FROM packets);
|
||||
END IF;
|
||||
|
||||
-- Try to get current value
|
||||
BEGIN
|
||||
current_val := currval('packet_count_seq');
|
||||
EXCEPTION
|
||||
WHEN object_not_in_prerequisite_state THEN
|
||||
-- If currval hasn't been called yet, get last_value
|
||||
SELECT last_value INTO current_val FROM packet_count_seq;
|
||||
END;
|
||||
|
||||
-- If sequence is at 0 and hasn't been used (is_called = false), return 0
|
||||
IF current_val = 0 THEN
|
||||
RETURN 0;
|
||||
ELSE
|
||||
RETURN current_val;
|
||||
END IF;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql STABLE;
|
||||
"""
|
||||
end
|
||||
|
||||
def down do
|
||||
# Drop the event trigger
|
||||
execute "DROP EVENT TRIGGER IF EXISTS reset_packet_counter_trigger;"
|
||||
|
||||
# Drop the reset functions
|
||||
execute "DROP FUNCTION IF EXISTS reset_packet_counter_on_truncate();"
|
||||
execute "DROP FUNCTION IF EXISTS reset_packet_counter();"
|
||||
|
||||
# Restore the original get_packet_count function
|
||||
execute """
|
||||
CREATE OR REPLACE FUNCTION get_packet_count()
|
||||
RETURNS BIGINT AS $$
|
||||
BEGIN
|
||||
RETURN currval('packet_count_seq');
|
||||
EXCEPTION
|
||||
WHEN object_not_in_prerequisite_state THEN
|
||||
-- If currval hasn't been called yet in this session, get the last value
|
||||
RETURN last_value FROM packet_count_seq;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql STABLE;
|
||||
"""
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue