20260209135254_2e552754-4888-4426-a9e8-7b225eacab90.sql 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. CREATE OR REPLACE FUNCTION public.purge_old_articles()
  2. RETURNS TABLE(deleted_count integer, admin_emails text[])
  3. LANGUAGE plpgsql
  4. SECURITY DEFINER
  5. SET search_path TO 'public'
  6. AS $function$
  7. DECLARE
  8. v_deleted_count INTEGER;
  9. v_admin_emails TEXT[];
  10. v_cutoff_date TIMESTAMP WITH TIME ZONE;
  11. BEGIN
  12. v_cutoff_date := NOW() - INTERVAL '48 hours';
  13. SELECT ARRAY_AGG(email) INTO v_admin_emails
  14. FROM public.super_users;
  15. WITH articles_to_delete AS (
  16. SELECT a.id
  17. FROM public.articles a
  18. WHERE a.last_seen_at < v_cutoff_date
  19. -- Exclure les articles épinglés
  20. AND NOT EXISTS (
  21. SELECT 1 FROM public.user_articles ua
  22. WHERE ua.article_id = a.id AND ua.is_pinned = true
  23. )
  24. -- Exclure les articles non lus dont le flux a au moins un abonné
  25. AND NOT (
  26. NOT EXISTS (
  27. SELECT 1 FROM public.user_articles ua
  28. WHERE ua.article_id = a.id AND ua.is_read = true
  29. )
  30. AND EXISTS (
  31. SELECT 1 FROM public.user_feeds uf
  32. WHERE uf.feed_id = a.feed_id AND uf.is_followed = true
  33. )
  34. )
  35. LIMIT 1000
  36. ),
  37. deleted_user_articles AS (
  38. DELETE FROM public.user_articles
  39. WHERE article_id IN (SELECT id FROM articles_to_delete)
  40. RETURNING article_id
  41. ),
  42. deleted AS (
  43. DELETE FROM public.articles
  44. WHERE id IN (SELECT id FROM articles_to_delete)
  45. RETURNING id
  46. )
  47. SELECT COUNT(*)::INTEGER INTO v_deleted_count FROM deleted;
  48. RAISE NOTICE 'Purge automatique: % articles supprimés (non vus depuis 48h, non épinglés, non protégés par abonnement)', v_deleted_count;
  49. RETURN QUERY SELECT v_deleted_count, v_admin_emails;
  50. END;
  51. $function$;
  52. CREATE OR REPLACE FUNCTION public.test_purge_articles()
  53. RETURNS TABLE(articles_to_delete integer, oldest_article_date timestamp with time zone, newest_article_date timestamp with time zone, sample_titles text[])
  54. LANGUAGE plpgsql
  55. SECURITY DEFINER
  56. SET search_path TO 'public'
  57. AS $function$
  58. DECLARE
  59. v_cutoff_date TIMESTAMP WITH TIME ZONE;
  60. BEGIN
  61. v_cutoff_date := NOW() - INTERVAL '48 hours';
  62. RETURN QUERY
  63. WITH eligible_articles AS (
  64. SELECT a.id, a.last_seen_at, a.title
  65. FROM public.articles a
  66. WHERE a.last_seen_at < v_cutoff_date
  67. AND NOT EXISTS (
  68. SELECT 1 FROM public.user_articles ua
  69. WHERE ua.article_id = a.id AND ua.is_pinned = true
  70. )
  71. AND NOT (
  72. NOT EXISTS (
  73. SELECT 1 FROM public.user_articles ua
  74. WHERE ua.article_id = a.id AND ua.is_read = true
  75. )
  76. AND EXISTS (
  77. SELECT 1 FROM public.user_feeds uf
  78. WHERE uf.feed_id = a.feed_id AND uf.is_followed = true
  79. )
  80. )
  81. ),
  82. sample_articles AS (
  83. SELECT title FROM eligible_articles ORDER BY last_seen_at DESC LIMIT 5
  84. )
  85. SELECT
  86. (SELECT COUNT(*)::INTEGER FROM eligible_articles),
  87. (SELECT MIN(last_seen_at) FROM eligible_articles),
  88. (SELECT MAX(last_seen_at) FROM eligible_articles),
  89. (SELECT ARRAY_AGG(title) FROM sample_articles);
  90. END;
  91. $function$;