diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-18 09:24:10 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-18 09:24:10 +0000 |
| commit | 85d621c791efaad1245c1aec8e5185a1eb78c7b9 (patch) | |
| tree | c14544af0970c3a8a9519d697e48ae7de0f707b3 /src/purgatory/sync/context.rs | |
| parent | 0c01797812bb77fc81d0efe58f0e7858f2b7af66 (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/purgatory/sync/context.rs')
| -rw-r--r-- | src/purgatory/sync/context.rs | 18 |
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> { |