From 0b9861e14f23cc615d33ebd8845a36b40516a8a5 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Tue, 24 Feb 2026 09:19:02 +0000 Subject: Fix purgatory announcement not promoted when OIDs arrive via cross-owner state event copy When git data is fetched into owner A's repo and a state event for owner B is released from purgatory (copying OIDs from A's repo to B's repo via process_state_with_git_data), owner B's purgatory announcement was never promoted. process_purgatory_announcements only promotes the announcement for the owner derived from source_repo_path (owner A), so owner B's announcement stayed in purgatory with its 30-minute expiry timer running. 30 minutes later the cleanup task would soft-expire owner B's entry, deleting the bare repository even though the announcement had been effectively satisfied. Fix: after a state event is successfully saved to the database, iterate over all announcements in db_repo_data and promote any purgatory announcement for owners whose repos received OIDs via the copy (i.e. repos other than source_repo_path). --- src/git/sync.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'src/git') diff --git a/src/git/sync.rs b/src/git/sync.rs index c24d16b..0d9a6b5 100644 --- a/src/git/sync.rs +++ b/src/git/sync.rs @@ -1076,6 +1076,57 @@ async fn process_purgatory_state_events( event_id = %entry.event.id, "Released state event from purgatory" ); + + // Promote purgatory announcements for repos that received OIDs via + // the state event copy above. + // + // process_state_with_git_data copies OIDs from source_repo_path to every + // other owner repo listed in db_repo_data.announcements. When an + // announcement for one of those owners is still in purgatory (e.g. the + // meshman announcement waiting while c03rad0's state event triggered the + // copy), the announcement would never be promoted because + // process_purgatory_announcements only promotes the owner derived from + // source_repo_path. Without this promotion the purgatory expiry timer + // keeps running and eventually deletes the bare repo even though the + // announcement was effectively satisfied. + for announcement in &db_repo_data.announcements { + let target_repo_path = git_data_path.join(announcement.repo_path()); + if target_repo_path == source_repo_path { + // This is the source repo — already handled by + // process_purgatory_announcements called before us. + continue; + } + let owner = &announcement.event.pubkey; + if let Some(ann_event) = purgatory.promote_announcement(owner, identifier) { + match database.save_event(&ann_event).await { + Ok(_) => { + info!( + identifier = %identifier, + owner = %owner, + event_id = %ann_event.id, + "Promoted purgatory announcement for owner whose repo received OIDs via state event copy" + ); + if let Some(relay) = local_relay { + relay.notify_event(ann_event.clone()); + } + result.announcements_released += 1; + } + Err(e) => { + warn!( + identifier = %identifier, + owner = %owner, + event_id = %ann_event.id, + error = %e, + "Failed to save promoted announcement to database" + ); + result.errors.push(format!( + "Failed to save promoted announcement for owner {}: {}", + owner, e + )); + } + } + } + } } Err(e) => { warn!( -- cgit v1.2.3