🚧 Add message delete

This commit is contained in:
Jonas Bengtsson
2026-09-06 22:35:24 +02:00
parent 64847b9ca1
commit f3fc394c0c
7 changed files with 797 additions and 3 deletions
+35
View File
@@ -107,6 +107,41 @@ COMMENT ON TABLE imei_attributes IS
COMMENT ON COLUMN imei_attributes.effective_from IS
'Time from which the value applies; backdating allowed. Resolved against the device timestamp (payload_time, received_at fallback) in GET /messages.';
-- Soft-delete retention for mqtt_messages: a "delete" MOVES the row here
-- (unchanged, including its ORIGINAL id) instead of dropping it. Retained
-- rows are auto-purged when expires_at passes (the API purges expired rows
-- lazily on every retention read). Restoring moves the row back with the
-- SAME id - safe by construction: the move is a single atomic statement,
-- so an id never exists in both tables, and the BIGSERIAL never regenerates
-- an id that was handed out. NOT BIGSERIAL here: ids always come from the
-- original mqtt_messages row. A separate mirror table (not a flag column)
-- keeps every existing read path (GET /messages, counts, facets, export,
-- rename, attribute resolution) untouched.
CREATE TABLE IF NOT EXISTS mqtt_messages_retention (
id BIGINT PRIMARY KEY,
received_at TIMESTAMPTZ NOT NULL,
topic TEXT NOT NULL,
imei TEXT NOT NULL,
device TEXT NOT NULL,
payload JSONB NOT NULL,
payload_time TIMESTAMPTZ,
deleted_at TIMESTAMPTZ NOT NULL DEFAULT now(),
deleted_by TEXT,
expires_at TIMESTAMPTZ NOT NULL
);
-- the lazy purge is a single indexed comparison
CREATE INDEX IF NOT EXISTS idx_retention_expires
ON mqtt_messages_retention (expires_at);
-- newest deletions first (the dialog lists recent deletions)
CREATE INDEX IF NOT EXISTS idx_retention_deleted_at
ON mqtt_messages_retention (deleted_at DESC);
COMMENT ON TABLE mqtt_messages_retention IS
'Messages soft-deleted from mqtt_messages: moved here (same id) on delete, restorable until expires_at, auto-purged by the API afterwards.';
COMMENT ON COLUMN mqtt_messages_retention.deleted_by IS
'Username of the deleting session user; NULL when deleted via an app token.';
-- Interactive users for the management UI: username/password login with a
-- role. 'admin' (level 2) manages everything incl. users; 'superuser'
-- (level 1) configures devices/configs/tokens and manages day-to-day