upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-02-18 09:24:10 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-02-18 09:24:10 +0000
commit85d621c791efaad1245c1aec8e5185a1eb78c7b9 (patch)
treec14544af0970c3a8a9519d697e48ae7de0f707b3 /src
parent0c01797812bb77fc81d0efe58f0e7858f2b7af66 (diff)
fix: break circular deadlock in sync loop by including purgatory in URL lookup
The sync loop calls fetch_repository_data() to get clone URLs so it knows where to fetch git data from. Previously this only queried the database, which means an announcement still in purgatory (no git data yet) would return no clone URLs, so the sync loop could never fetch the git data needed to promote the announcement - a circular deadlock. Fix by switching to fetch_repository_data_with_purgatory() which combines database announcements with purgatory announcements. Update the trait method's doc comment to document this behaviour. The mock implementation in tests is unaffected since it returns pre-configured data rather than delegating to either function.
Diffstat (limited to 'src')
-rw-r--r--src/purgatory/sync/context.rs18
1 files changed, 16 insertions, 2 deletions
diff --git a/src/purgatory/sync/context.rs b/src/purgatory/sync/context.rs
index 33c2d12..3568e89 100644
--- a/src/purgatory/sync/context.rs
+++ b/src/purgatory/sync/context.rs
@@ -75,7 +75,12 @@ pub trait SyncContext: Send + Sync {
75 /// # Returns 75 /// # Returns
76 /// Set of clone URLs from PR events in purgatory for this identifier 76 /// Set of clone URLs from PR events in purgatory for this identifier
77 fn collect_pr_clone_urls(&self, identifier: &str) -> HashSet<String>; 77 fn collect_pr_clone_urls(&self, identifier: &str) -> HashSet<String>;
78 /// Get repository data (announcements, clone URLs, etc.) from the database. 78 /// Get repository data (announcements, clone URLs, etc.) from the database and purgatory.
79 ///
80 /// Checks both the database (promoted announcements) and purgatory (announcements
81 /// awaiting git data). This is necessary to obtain clone URLs when an announcement
82 /// has not yet been promoted - without purgatory data, the sync loop would have no
83 /// URLs to fetch from and the announcement could never be promoted (circular deadlock).
79 /// 84 ///
80 /// # Arguments 85 /// # Arguments
81 /// * `identifier` - The repository identifier (d-tag value) 86 /// * `identifier` - The repository identifier (d-tag value)
@@ -279,7 +284,16 @@ impl SyncContext for RealSyncContext {
279 } 284 }
280 285
281 async fn fetch_repository_data(&self, identifier: &str) -> Result<RepositoryData> { 286 async fn fetch_repository_data(&self, identifier: &str) -> Result<RepositoryData> {
282 crate::git::authorization::fetch_repository_data(&self.database, identifier).await 287 // Use the purgatory-aware variant so that clone URLs from announcements still
288 // in purgatory (not yet promoted) are available. Without this, the sync loop
289 // would find no URLs to fetch from and the announcement could never be promoted
290 // (circular deadlock: can't promote without git data, can't get git data without URLs).
291 crate::git::authorization::fetch_repository_data_with_purgatory(
292 &self.database,
293 &self.purgatory,
294 identifier,
295 )
296 .await
283 } 297 }
284 298
285 fn collect_needed_oids(&self, identifier: &str) -> HashSet<String> { 299 fn collect_needed_oids(&self, identifier: &str) -> HashSet<String> {