Noreposts Feed

Add cleanup for inactive user follows

- Add cleanup_inactive_user_follows() function to remove follows for users who haven't accessed the feed
- Runs every 5 minutes in the cleanup task
- Removes follows for any user not in active_users table (7 day window)
- Prevents storing unnecessary follow data for the entire Bluesky network

+49 -2
+3 -2
.claude/settings.local.json
··· 2 2 "permissions": { 3 3 "allow": [ 4 4 "Read(//home/vitorpy/code/vitorpy.com/**)", 5 - "Bash(gh issue view:*)" 5 + "Bash(gh issue view:*)", 6 + "Bash(ssh:*)" 6 7 ], 7 8 "deny": [], 8 9 "ask": [] 9 10 } 10 - } 11 + }
+40
src/cleanup.rs
··· 34 34 Ok(()) 35 35 } 36 36 37 + pub async fn cleanup_inactive_user_follows(db: Arc<Database>) -> Result<()> { 38 + info!("Starting cleanup of follows for inactive users"); 39 + 40 + // Get all unique follower DIDs from the follows table 41 + let all_follower_dids: Vec<String> = sqlx::query("SELECT DISTINCT follower_did FROM follows") 42 + .fetch_all(&db.pool) 43 + .await? 44 + .into_iter() 45 + .filter_map(|row| row.try_get("follower_did").ok()) 46 + .collect(); 47 + 48 + info!("Found {} unique users with follows", all_follower_dids.len()); 49 + 50 + // Get active users (accessed feed in last 7 days) 51 + let active_users = db.get_active_users(7).await?; 52 + let active_user_set: std::collections::HashSet<String> = 53 + active_users.into_iter().collect(); 54 + 55 + // Delete follows for users who are not active 56 + let mut deleted_count = 0; 57 + for follower_did in all_follower_dids { 58 + if !active_user_set.contains(&follower_did) { 59 + let result = sqlx::query("DELETE FROM follows WHERE follower_did = ?") 60 + .bind(&follower_did) 61 + .execute(&db.pool) 62 + .await?; 63 + 64 + deleted_count += result.rows_affected(); 65 + } 66 + } 67 + 68 + if deleted_count > 0 { 69 + info!("Cleaned up {} follows from inactive users", deleted_count); 70 + } else { 71 + info!("No inactive user follows to clean up"); 72 + } 73 + 74 + Ok(()) 75 + } 76 + 37 77 async fn verify_follows_for_user( 38 78 client: &reqwest::Client, 39 79 db: Arc<Database>,
+6
src/main.rs
··· 128 128 if let Err(e) = cleanup::verify_active_user_follows(Arc::clone(&db_cleanup)).await { 129 129 warn!("Failed to verify active user follows: {}", e); 130 130 } 131 + 132 + // Clean up follows for users who haven't accessed the feed 133 + // This removes all follow data for users not in the active_users table 134 + if let Err(e) = cleanup::cleanup_inactive_user_follows(Arc::clone(&db_cleanup)).await { 135 + warn!("Failed to cleanup inactive user follows: {}", e); 136 + } 131 137 } 132 138 }); 133 139