mirror of
https://github.com/penpot/penpot.git
synced 2026-11-07 10:30:40 +00:00
* ✨ Migrate legacy file payloads to file_data and delete orphans Copy file.data and labelled file_change.data to file_data on boot (type main/snapshot, backend db, deleted_at preserved), then delete file_change rows with data but no label, which no read path reaches. Large instances pre-migrate with batched statements and fake this step. Closes #12784. AI-assisted-by: muse-spark-1.3-contributor * 📚 Add 2.19.0 operations runbook for legacy file_data migration Manual pre-migration procedure for big instances, same statements as migration 0157 in batched transactions, following the convention of the file-change partition runbook. Closes #12784. AI-assisted-by: muse-spark-1.3-contributor * 🐛 Address review feedback on the legacy file data migration Fix the issues raised in the review of the migration that moves the legacy file payloads to file_data. The migration deletes the unlabelled file_change rows that carry data, but restore-files still cleared their date, and the retention test asserted they came back. A row without a date never reaches objects-gc, which is the leak fixed in #12419. Restore now unmarks only snapshots, the rows that carry a label, and the retention test checks that the legacy payload keeps its date instead of coming back. Cover the conflict path that had no test: a pre-existing snapshot that collides with a labelled change row, and a second run that must leave the legacy columns null and the orphan row absent. The runbook analyses file_data after the inserts, so the planner does not wait for autovacuum. Drop app.srepl.procs.fdata-storage: the copy it performed is what the migration replaces and nothing requires it. Closes #12784 AI-assisted-by: deepseek-v4.1-flash
56 lines
2.0 KiB
SQL
56 lines
2.0 KiB
SQL
-- Migrate legacy payloads to file_data: labelled file_change.data as
|
|
-- snapshots, file.data as mains (backend 'db', deleted_at copied so the
|
|
-- GC keeps collecting them), then delete orphan file_change rows with
|
|
-- data but no label (no read path reaches them).
|
|
--
|
|
-- Idempotent: INSERTs ignore conflicts, UPDATEs only null the legacy
|
|
-- column where the file_data row exists. Big instances pre-migrate by
|
|
-- hand (operations/2.19.0-migrate-legacy-file-data.md) and fake this
|
|
-- step instead:
|
|
--
|
|
-- INSERT INTO migrations (module, step)
|
|
-- VALUES ('main', '0157-migrate-legacy-file-data');
|
|
|
|
INSERT INTO file_data (file_id, id, created_at, modified_at, deleted_at,
|
|
type, backend, metadata, data)
|
|
SELECT file_id, id, created_at, updated_at, deleted_at,
|
|
'snapshot', 'db', NULL, data
|
|
FROM file_change
|
|
WHERE data IS NOT NULL
|
|
AND label IS NOT NULL
|
|
ON CONFLICT (file_id, id) DO NOTHING;
|
|
|
|
UPDATE file_change AS fc
|
|
SET data = NULL
|
|
WHERE fc.data IS NOT NULL
|
|
AND fc.label IS NOT NULL
|
|
AND EXISTS (SELECT 1
|
|
FROM file_data AS fd
|
|
WHERE fd.file_id = fc.file_id
|
|
AND fd.id = fc.id
|
|
AND fd.type = 'snapshot');
|
|
|
|
INSERT INTO file_data (file_id, id, created_at, modified_at, deleted_at,
|
|
type, backend, metadata, data)
|
|
SELECT id, id, created_at, modified_at, deleted_at,
|
|
'main', 'db', NULL, data
|
|
FROM file
|
|
WHERE data IS NOT NULL
|
|
ON CONFLICT (file_id, id) DO NOTHING;
|
|
|
|
UPDATE file AS f
|
|
SET data = NULL
|
|
WHERE f.data IS NOT NULL
|
|
AND EXISTS (SELECT 1
|
|
FROM file_data AS fd
|
|
WHERE fd.file_id = f.id
|
|
AND fd.id = f.id
|
|
AND fd.type = 'main');
|
|
|
|
-- Orphan revisions: legacy payloads without label. No file_data row
|
|
-- corresponds to them (snapshots are told apart by label), so there is
|
|
-- nothing to copy; the row itself is garbage. Delete it.
|
|
DELETE FROM file_change
|
|
WHERE data IS NOT NULL
|
|
AND label IS NULL;
|