aprs.me/priv/repo/migrations/20260726000002_replace_packet_count_sequence.exs
Graham McIntire b0832e5a9c
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 2s
refactor: harden packet delivery and operations
2026-07-26 13:11:26 -05:00

147 lines
3.6 KiB
Elixir

defmodule Aprsme.Repo.Migrations.ReplacePacketCountSequence do
use Ecto.Migration
def up do
execute("DROP TRIGGER IF EXISTS packet_insert_sequence ON packets")
execute("DROP TRIGGER IF EXISTS packet_delete_sequence ON packets")
execute("""
INSERT INTO packet_counters (counter_type, count, inserted_at, updated_at)
VALUES ('total_packets', 0, NOW(), NOW())
ON CONFLICT (counter_type) DO NOTHING
""")
execute("""
UPDATE packet_counters
SET count = (SELECT COUNT(*) FROM packets),
updated_at = NOW()
WHERE counter_type = 'total_packets'
""")
execute("""
CREATE OR REPLACE FUNCTION increment_packet_counter()
RETURNS TRIGGER AS $$
BEGIN
UPDATE packet_counters
SET count = count + 1,
updated_at = NOW()
WHERE counter_type = 'total_packets';
RETURN NEW;
END;
$$ LANGUAGE plpgsql
""")
execute("""
CREATE OR REPLACE FUNCTION decrement_packet_counter()
RETURNS TRIGGER AS $$
BEGIN
UPDATE packet_counters
SET count = GREATEST(0, count - 1),
updated_at = NOW()
WHERE counter_type = 'total_packets';
RETURN OLD;
END;
$$ LANGUAGE plpgsql
""")
execute("""
CREATE TRIGGER packet_insert_counter
AFTER INSERT ON packets
FOR EACH ROW
EXECUTE FUNCTION increment_packet_counter()
""")
execute("""
CREATE TRIGGER packet_delete_counter
AFTER DELETE ON packets
FOR EACH ROW
EXECUTE FUNCTION decrement_packet_counter()
""")
execute("""
CREATE OR REPLACE FUNCTION get_packet_count()
RETURNS BIGINT AS $$
BEGIN
RETURN COALESCE(
(SELECT count FROM packet_counters WHERE counter_type = 'total_packets'),
0
);
END;
$$ LANGUAGE plpgsql STABLE
""")
execute("DROP FUNCTION IF EXISTS increment_packet_sequence()")
execute("DROP FUNCTION IF EXISTS decrement_packet_sequence()")
execute("DROP SEQUENCE IF EXISTS packet_count_seq")
execute("""
COMMENT ON TABLE packet_counters IS
'Exact retained packet count. Updated atomically by packet DML and partition maintenance.'
""")
end
def down do
execute("DROP TRIGGER IF EXISTS packet_insert_counter ON packets")
execute("DROP TRIGGER IF EXISTS packet_delete_counter ON packets")
execute("""
CREATE SEQUENCE packet_count_seq
MINVALUE 0
START WITH 0
""")
execute("""
SELECT setval(
'packet_count_seq',
COALESCE((SELECT count FROM packet_counters WHERE counter_type = 'total_packets'), 0),
true
)
""")
execute("""
CREATE OR REPLACE FUNCTION increment_packet_sequence()
RETURNS TRIGGER AS $$
BEGIN
PERFORM nextval('packet_count_seq');
RETURN NEW;
END;
$$ LANGUAGE plpgsql
""")
execute("""
CREATE OR REPLACE FUNCTION decrement_packet_sequence()
RETURNS TRIGGER AS $$
DECLARE
current_val BIGINT;
BEGIN
SELECT last_value INTO current_val FROM packet_count_seq;
PERFORM setval('packet_count_seq', GREATEST(0, current_val - 1), true);
RETURN OLD;
END;
$$ LANGUAGE plpgsql
""")
execute("""
CREATE TRIGGER packet_insert_sequence
AFTER INSERT ON packets
FOR EACH ROW
EXECUTE FUNCTION increment_packet_sequence()
""")
execute("""
CREATE TRIGGER packet_delete_sequence
AFTER DELETE ON packets
FOR EACH ROW
EXECUTE FUNCTION decrement_packet_sequence()
""")
execute("""
CREATE OR REPLACE FUNCTION get_packet_count()
RETURNS BIGINT AS $$
BEGIN
RETURN last_value FROM packet_count_seq;
END;
$$ LANGUAGE plpgsql STABLE
""")
end
end