Client side atproto account migrator in your web browser, along with services for backups and adversarial migrations.
0

Configure Feed

Select the types of activity you want to include in your feed.

pds-moover / shared / src / jobs / verify_backups.rs
2.6 kB 76 lines
1use crate::db::models::{BlobModel, BlobType}; 2use crate::storage::{blob_backup_path, repo_backup_path}; 3use anyhow::Result; 4use s3::Bucket; 5use sqlx::{Pool, Postgres}; 6 7/// Verifies that all blobs in the database exist in S3. 8/// Returns a Vec of missing blob information (did, cid_or_rev, blob_type). 9pub async fn verify_backups(pool: &Pool<Postgres>, s3_bucket: &Bucket) -> Result<Vec<MissingBlob>> { 10 // Get all blobs from the database 11 let blobs = sqlx::query_as::<_, BlobModel>("SELECT * FROM blobs ORDER BY created_at") 12 .fetch_all(pool) 13 .await?; 14 15 let total_blobs = blobs.len(); 16 log::info!("Checking {} blobs in S3...", total_blobs); 17 18 let mut missing_blobs = Vec::new(); 19 let mut checked = 0; 20 21 for blob in blobs { 22 checked += 1; 23 if checked % 100 == 0 { 24 log::info!("Checked {}/{} blobs...", checked, total_blobs); 25 } 26 27 let s3_path = match blob.r#type { 28 BlobType::Repo => repo_backup_path(blob.account_did.clone()), 29 BlobType::Blob => blob_backup_path(blob.account_did.clone(), blob.cid_or_rev.clone()), 30 BlobType::Prefs => { 31 // Handle prefs if needed - for now skip 32 log::debug!("Skipping prefs blob: {:?}", blob); 33 continue; 34 } 35 }; 36 37 // Check if the object exists in S3 38 match s3_bucket.head_object(&s3_path).await { 39 Ok(_) => { 40 // Object exists, all good 41 log::debug!("✓ Found: {}", s3_path); 42 } 43 Err(e) => { 44 // Check if it's a 404 error (not found) 45 if e.to_string().contains("404") { 46 log::warn!("✗ Missing: {}", s3_path); 47 missing_blobs.push(MissingBlob { 48 did: blob.account_did.clone(), 49 cid_or_rev: blob.cid_or_rev.clone(), 50 blob_type: blob.r#type.clone(), 51 s3_path, 52 }); 53 } else { 54 // Some other error - log it but don't count as missing 55 log::error!("Error checking {}: {}", s3_path, e); 56 } 57 } 58 } 59 } 60 61 log::info!( 62 "Verification complete. Checked {} blobs, found {} missing.", 63 checked, 64 missing_blobs.len() 65 ); 66 67 Ok(missing_blobs) 68} 69 70#[derive(Debug, Clone)] 71pub struct MissingBlob { 72 pub did: String, 73 pub cid_or_rev: String, 74 pub blob_type: BlobType, 75 pub s3_path: String, 76}