diff --git a/release/migrate_cleanup_inactive_identities.sql b/release/migrate_cleanup_inactive_identities.sql new file mode 100644 index 0000000..9e647e8 --- /dev/null +++ b/release/migrate_cleanup_inactive_identities.sql @@ -0,0 +1,33 @@ +-- Identity Inactive Cleanup Migration +-- Date: 2026-05-14 +-- Purpose: Mark auto-generated identities with no face_detection references as 'inactive' +-- Run after pipeline completes to clean up orphaned auto identities + +BEGIN; + +-- Mark auto identities as inactive if they have zero face_detection references +UPDATE identities +SET status = 'inactive', + metadata = metadata || jsonb_build_object('inactivated_at', NOW()::text, 'reason', 'no_face_references') +WHERE source = 'auto' + AND status != 'inactive' + AND id NOT IN ( + SELECT DISTINCT identity_id FROM face_detections WHERE identity_id IS NOT NULL + ); + +-- Delete identity_bindings pointing to newly inactive identities +DELETE FROM identity_bindings +WHERE identity_id IN ( + SELECT id FROM identities WHERE status = 'inactive' +); + +-- Log +DO $$ +DECLARE + marked INT; +BEGIN + SELECT COUNT(*) INTO marked FROM identities WHERE status = 'inactive' AND metadata->>'reason' = 'no_face_references'; + RAISE NOTICE 'Marked % auto identities as inactive (no face references)', marked; +END $$; + +COMMIT; diff --git a/src/bin/release.rs b/src/bin/release.rs index d3edc4a..874a457 100644 --- a/src/bin/release.rs +++ b/src/bin/release.rs @@ -406,12 +406,12 @@ async fn cmd_package(db: &PostgresDb, uuid: &str) -> Result<()> { // Export identities with file_uuid (direct column, no JOIN needed) // FILE LOCAL: file_uuid = '{uuid}' - // GLOBAL (cross-file): tmdb identities + user-defined (exclude inactive auto) + // GLOBAL (cross-file): tmdb identities + user-defined (exclude inactive auto + status='inactive') let idents_name = "dev_identities"; let idents_path = sql_dir.join(format!("{}.sql", idents_name)); { let idents_query = format!( - "COPY (SELECT * FROM dev.identities WHERE file_uuid = '{}' OR (file_uuid IS NULL AND source IN ('tmdb', 'merged', 'user_defined'))) TO STDOUT WITH CSV HEADER", uuid + "COPY (SELECT * FROM dev.identities WHERE (file_uuid = '{}' OR (file_uuid IS NULL AND source IN ('tmdb', 'merged', 'user_defined'))) AND status IS DISTINCT FROM 'inactive') TO STDOUT WITH CSV HEADER", uuid ); let cols = psql_exec(&format!( "SELECT string_agg(column_name, ', ' ORDER BY ordinal_position) FROM information_schema.columns WHERE table_schema='dev' AND table_name='identities' AND is_updatable='YES'"