Our Personal Data Server from scratch!
0

Configure Feed

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

tranquil-store/repo: repair tolerates corrupt/missing blocks

Lewis: May this revision serve well! <lu5a@proton.me>

author
Lewis
date (Jun 26, 2026, 8:50 PM +0300) commit a1715182 parent 28f2e040 change-id wputuvso
+23 -21
+17 -21
crates/tranquil-pds/src/repo_ops.rs
··· 300 300 })?; 301 301 302 302 if outcome.nodes_repaired > 0 { 303 - let block_cids = 304 - crate::scheduled::collect_current_repo_blocks(&state.block_store, &current_root_cid) 305 - .await 306 - .map_err(|e| { 307 - error!("repair: re-walk for user_blocks backfill failed: {}", e); 308 - ApiError::InternalError(None) 309 - })?; 310 - 311 - let cids = block_cids 312 - .iter() 313 - .map(|bytes| Cid::try_from(bytes.as_slice())) 314 - .collect::<Result<Vec<Cid>, _>>() 315 - .map_err(|e| { 316 - error!("repair: unparseable CID in repaired DAG walk: {e}"); 317 - ApiError::InternalError(None) 318 - })?; 319 - let present = state.block_store.get_many(&cids).await.map_err(|e| { 320 - error!("repair: presence check during user_blocks backfill failed: {e}"); 303 + let leaf_present = futures::future::try_join_all( 304 + entries.iter().map(|(_, cid)| state.block_store.has(cid)), 305 + ) 306 + .await 307 + .map_err(|e| { 308 + error!("repair: leaf presence check failed: {e}"); 321 309 ApiError::InternalError(None) 322 310 })?; 323 - let missing: Vec<Cid> = cids 311 + let missing: Vec<Cid> = entries 324 312 .iter() 325 - .zip(present) 326 - .filter_map(|(cid, found)| found.is_none().then_some(*cid)) 313 + .zip(leaf_present) 314 + .filter_map(|((_, cid), present)| (!present).then_some(*cid)) 327 315 .collect(); 328 316 if !missing.is_empty() { 329 317 error!( ··· 337 325 missing.len() 338 326 )))); 339 327 } 328 + 329 + let block_cids = 330 + crate::scheduled::collect_current_repo_blocks(&state.block_store, &current_root_cid) 331 + .await 332 + .map_err(|e| { 333 + error!("repair: re-walk for user_blocks backfill failed: {}", e); 334 + ApiError::InternalError(None) 335 + })?; 340 336 341 337 state 342 338 .repos
+6
crates/tranquil-pds/src/scheduled.rs
··· 180 180 let block = match block_store.get(&cid).await { 181 181 Ok(Some(b)) => b, 182 182 Ok(None) => continue, 183 + Err(e) 184 + if crate::api::error::ApiError::detail_is_repo_corruption(&format!("{e:#}")) => 185 + { 186 + warn!(cid = %cid, error = %format!("{e:#}"), "skipping corrupt block during repo walk"); 187 + continue; 188 + } 183 189 Err(e) => anyhow::bail!("Failed to get block {}: {:?}", cid, e), 184 190 }; 185 191