diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-24 11:36:39 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-24 11:36:39 +0000 |
| commit | c31a313ccf781e54fa15942bc882c1b113d3f590 (patch) | |
| tree | 0dec673c40a7cff42651c290b8ded5f6d063a8ae /src | |
| parent | 5efdf431a1481f6fb7a17190b62588b81c5b1e65 (diff) | |
rename: fetch_repository_data -> fetch_repository_data_{excluding,with}_purgatory
The old name was ambiguous - it wasn't clear whether purgatory was
included or not. The two variants are now explicitly named:
- fetch_repository_data_excluding_purgatory: DB only
- fetch_repository_data_with_purgatory: DB + purgatory overlay
SyncContext trait method also renamed to fetch_repository_data_with_purgatory
to match the free function it delegates to.
Diffstat (limited to 'src')
| -rw-r--r-- | src/git/authorization.rs | 6 | ||||
| -rw-r--r-- | src/git/sync.rs | 45 | ||||
| -rw-r--r-- | src/nostr/policy/pr_event.rs | 6 | ||||
| -rw-r--r-- | src/purgatory/sync/context.rs | 17 | ||||
| -rw-r--r-- | src/purgatory/sync/functions.rs | 6 |
5 files changed, 45 insertions, 35 deletions
diff --git a/src/git/authorization.rs b/src/git/authorization.rs index 0e9a8ba..bf49800 100644 --- a/src/git/authorization.rs +++ b/src/git/authorization.rs | |||
| @@ -234,7 +234,7 @@ pub struct RepositoryData { | |||
| 234 | /// | 234 | /// |
| 235 | /// This performs a single database query to fetch both announcement and state events, | 235 | /// This performs a single database query to fetch both announcement and state events, |
| 236 | /// which is more efficient than separate queries. | 236 | /// which is more efficient than separate queries. |
| 237 | pub async fn fetch_repository_data( | 237 | pub async fn fetch_repository_data_excluding_purgatory( |
| 238 | database: &SharedDatabase, | 238 | database: &SharedDatabase, |
| 239 | identifier: &str, | 239 | identifier: &str, |
| 240 | ) -> Result<RepositoryData> { | 240 | ) -> Result<RepositoryData> { |
| @@ -298,7 +298,7 @@ pub async fn fetch_repository_data_with_purgatory( | |||
| 298 | identifier: &str, | 298 | identifier: &str, |
| 299 | ) -> Result<RepositoryData> { | 299 | ) -> Result<RepositoryData> { |
| 300 | // First, fetch from database | 300 | // First, fetch from database |
| 301 | let mut repo_data = fetch_repository_data(database, identifier).await?; | 301 | let mut repo_data = fetch_repository_data_excluding_purgatory(database, identifier).await?; |
| 302 | 302 | ||
| 303 | // Then, add announcements from purgatory | 303 | // Then, add announcements from purgatory |
| 304 | let purgatory_announcements = purgatory.get_announcements_by_identifier(identifier); | 304 | let purgatory_announcements = purgatory.get_announcements_by_identifier(identifier); |
| @@ -511,7 +511,7 @@ pub async fn get_authorization_from_db( | |||
| 511 | identifier: &str, | 511 | identifier: &str, |
| 512 | ) -> Result<AuthorizationResult> { | 512 | ) -> Result<AuthorizationResult> { |
| 513 | // Fetch all repository data with a single query | 513 | // Fetch all repository data with a single query |
| 514 | let repo_data = fetch_repository_data(database, identifier).await?; | 514 | let repo_data = fetch_repository_data_excluding_purgatory(database, identifier).await?; |
| 515 | 515 | ||
| 516 | if repo_data.announcements.is_empty() { | 516 | if repo_data.announcements.is_empty() { |
| 517 | return Ok(AuthorizationResult::denied( | 517 | return Ok(AuthorizationResult::denied( |
diff --git a/src/git/sync.rs b/src/git/sync.rs index 0d9a6b5..9a02ad4 100644 --- a/src/git/sync.rs +++ b/src/git/sync.rs | |||
| @@ -38,8 +38,8 @@ use tracing::{debug, info, warn}; | |||
| 38 | use nostr_sdk::Event; | 38 | use nostr_sdk::Event; |
| 39 | 39 | ||
| 40 | use crate::git::authorization::{ | 40 | use crate::git::authorization::{ |
| 41 | collect_authorized_maintainers, fetch_repository_data, fetch_repository_data_with_purgatory, | 41 | collect_authorized_maintainers, fetch_repository_data_excluding_purgatory, |
| 42 | RepositoryData, | 42 | fetch_repository_data_with_purgatory, RepositoryData, |
| 43 | }; | 43 | }; |
| 44 | use crate::git::{self, oid_exists}; | 44 | use crate::git::{self, oid_exists}; |
| 45 | use crate::nostr::builder::{Nip34WritePolicy, SharedDatabase}; | 45 | use crate::nostr::builder::{Nip34WritePolicy, SharedDatabase}; |
| @@ -933,20 +933,21 @@ async fn process_purgatory_state_events( | |||
| 933 | // IMPORTANT: Use fetch_repository_data_with_purgatory to include announcements | 933 | // IMPORTANT: Use fetch_repository_data_with_purgatory to include announcements |
| 934 | // that may still be in purgatory (not yet promoted). This ensures authorization | 934 | // that may still be in purgatory (not yet promoted). This ensures authorization |
| 935 | // works correctly even if the announcement promotion happens in the same batch. | 935 | // works correctly even if the announcement promotion happens in the same batch. |
| 936 | let mut db_repo_data = match fetch_repository_data_with_purgatory(database, purgatory, identifier).await { | 936 | let mut db_repo_data = |
| 937 | Ok(data) => data, | 937 | match fetch_repository_data_with_purgatory(database, purgatory, identifier).await { |
| 938 | Err(e) => { | 938 | Ok(data) => data, |
| 939 | warn!( | 939 | Err(e) => { |
| 940 | identifier = %identifier, | 940 | warn!( |
| 941 | error = %e, | 941 | identifier = %identifier, |
| 942 | "Failed to fetch repository data for purgatory state events" | 942 | error = %e, |
| 943 | ); | 943 | "Failed to fetch repository data for purgatory state events" |
| 944 | result | 944 | ); |
| 945 | .errors | 945 | result |
| 946 | .push(format!("Failed to fetch repo data: {}", e)); | 946 | .errors |
| 947 | return result; | 947 | .push(format!("Failed to fetch repo data: {}", e)); |
| 948 | } | 948 | return result; |
| 949 | }; | 949 | } |
| 950 | }; | ||
| 950 | 951 | ||
| 951 | // Process each state event in chronological order | 952 | // Process each state event in chronological order |
| 952 | for entry in &purgatory_states { | 953 | for entry in &purgatory_states { |
| @@ -1231,7 +1232,7 @@ async fn process_purgatory_pr_events( | |||
| 1231 | // NOTE: Only fetch from database, NOT purgatory. PR events should only be | 1232 | // NOTE: Only fetch from database, NOT purgatory. PR events should only be |
| 1232 | // released from purgatory when the announcement has been promoted (validated). | 1233 | // released from purgatory when the announcement has been promoted (validated). |
| 1233 | // This ensures we don't accept PR events for announcements that fail validation. | 1234 | // This ensures we don't accept PR events for announcements that fail validation. |
| 1234 | let db_repo_data = match fetch_repository_data(database, identifier).await { | 1235 | let db_repo_data = match fetch_repository_data_excluding_purgatory(database, identifier).await { |
| 1235 | Ok(data) => data, | 1236 | Ok(data) => data, |
| 1236 | Err(e) => { | 1237 | Err(e) => { |
| 1237 | warn!( | 1238 | warn!( |
| @@ -1372,7 +1373,9 @@ async fn process_purgatory_announcements( | |||
| 1372 | error = %e, | 1373 | error = %e, |
| 1373 | "Failed to parse owner pubkey" | 1374 | "Failed to parse owner pubkey" |
| 1374 | ); | 1375 | ); |
| 1375 | result.errors.push(format!("Failed to parse owner pubkey: {}", e)); | 1376 | result |
| 1377 | .errors | ||
| 1378 | .push(format!("Failed to parse owner pubkey: {}", e)); | ||
| 1376 | return result; | 1379 | return result; |
| 1377 | } | 1380 | } |
| 1378 | }; | 1381 | }; |
| @@ -1450,10 +1453,8 @@ async fn process_purgatory_announcements( | |||
| 1450 | } | 1453 | } |
| 1451 | 1454 | ||
| 1452 | // Re-process events from hot cache | 1455 | // Re-process events from hot cache |
| 1453 | let dummy_addr = SocketAddr::new( | 1456 | let dummy_addr = |
| 1454 | IpAddr::V4(Ipv4Addr::LOCALHOST), | 1457 | SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0); |
| 1455 | 0, | ||
| 1456 | ); | ||
| 1457 | for hot_event in hot_events { | 1458 | for hot_event in hot_events { |
| 1458 | info!( | 1459 | info!( |
| 1459 | event_id = %hot_event.id, | 1460 | event_id = %hot_event.id, |
diff --git a/src/nostr/policy/pr_event.rs b/src/nostr/policy/pr_event.rs index 072e445..52747a4 100644 --- a/src/nostr/policy/pr_event.rs +++ b/src/nostr/policy/pr_event.rs | |||
| @@ -7,7 +7,7 @@ use nostr_relay_builder::prelude::Event; | |||
| 7 | 7 | ||
| 8 | use super::PolicyContext; | 8 | use super::PolicyContext; |
| 9 | use crate::git; | 9 | use crate::git; |
| 10 | use crate::git::authorization::{collect_authorized_maintainers, fetch_repository_data}; | 10 | use crate::git::authorization::{collect_authorized_maintainers, fetch_repository_data_excluding_purgatory}; |
| 11 | 11 | ||
| 12 | /// Policy for validating PR and PR Update events | 12 | /// Policy for validating PR and PR Update events |
| 13 | #[derive(Clone)] | 13 | #[derive(Clone)] |
| @@ -131,7 +131,7 @@ impl PrEventPolicy { | |||
| 131 | // only be accepted for announcements that have been promoted (validated). | 131 | // only be accepted for announcements that have been promoted (validated). |
| 132 | // If the announcement is still in purgatory, the PR event should also go | 132 | // If the announcement is still in purgatory, the PR event should also go |
| 133 | // to purgatory and wait for the announcement to be promoted. | 133 | // to purgatory and wait for the announcement to be promoted. |
| 134 | let db_repo_data = fetch_repository_data(&self.ctx.database, &identifier).await?; | 134 | let db_repo_data = fetch_repository_data_excluding_purgatory(&self.ctx.database, &identifier).await?; |
| 135 | 135 | ||
| 136 | // Extract owner pubkey from source repo path | 136 | // Extract owner pubkey from source repo path |
| 137 | let owner_pubkey = crate::git::sync::extract_owner_from_repo_path( | 137 | let owner_pubkey = crate::git::sync::extract_owner_from_repo_path( |
| @@ -211,7 +211,7 @@ impl PrEventPolicy { | |||
| 211 | // only be accepted for announcements that have been promoted (validated). | 211 | // only be accepted for announcements that have been promoted (validated). |
| 212 | // If the announcement is still in purgatory, the PR event should also go | 212 | // If the announcement is still in purgatory, the PR event should also go |
| 213 | // to purgatory and wait for the announcement to be promoted. | 213 | // to purgatory and wait for the announcement to be promoted. |
| 214 | let db_repo_data = fetch_repository_data(&self.ctx.database, identifier).await?; | 214 | let db_repo_data = fetch_repository_data_excluding_purgatory(&self.ctx.database, identifier).await?; |
| 215 | 215 | ||
| 216 | // 3. Extract list of maintainers from "a 30617:<maintainer>:<identifier>" tags | 216 | // 3. Extract list of maintainers from "a 30617:<maintainer>:<identifier>" tags |
| 217 | let mut maintainer_pubkeys = std::collections::HashSet::new(); | 217 | let mut maintainer_pubkeys = std::collections::HashSet::new(); |
diff --git a/src/purgatory/sync/context.rs b/src/purgatory/sync/context.rs index 8297515..1bba961 100644 --- a/src/purgatory/sync/context.rs +++ b/src/purgatory/sync/context.rs | |||
| @@ -87,7 +87,10 @@ pub trait SyncContext: Send + Sync { | |||
| 87 | /// | 87 | /// |
| 88 | /// # Returns | 88 | /// # Returns |
| 89 | /// Repository data including announcements and state events | 89 | /// Repository data including announcements and state events |
| 90 | async fn fetch_repository_data(&self, identifier: &str) -> Result<RepositoryData>; | 90 | async fn fetch_repository_data_with_purgatory( |
| 91 | &self, | ||
| 92 | identifier: &str, | ||
| 93 | ) -> Result<RepositoryData>; | ||
| 91 | 94 | ||
| 92 | /// Get all OIDs needed for purgatory events with this identifier. | 95 | /// Get all OIDs needed for purgatory events with this identifier. |
| 93 | /// | 96 | /// |
| @@ -283,7 +286,10 @@ impl SyncContext for RealSyncContext { | |||
| 283 | urls | 286 | urls |
| 284 | } | 287 | } |
| 285 | 288 | ||
| 286 | async fn fetch_repository_data(&self, identifier: &str) -> Result<RepositoryData> { | 289 | async fn fetch_repository_data_with_purgatory( |
| 290 | &self, | ||
| 291 | identifier: &str, | ||
| 292 | ) -> Result<RepositoryData> { | ||
| 287 | // Use the purgatory-aware variant so that clone URLs from announcements still | 293 | // 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 | 294 | // 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 | 295 | // would find no URLs to fetch from and the announcement could never be promoted |
| @@ -585,7 +591,7 @@ pub mod mock { | |||
| 585 | /// assert_eq!(mock.fetch_log(), vec!["https://github.com/foo/bar.git"]); | 591 | /// assert_eq!(mock.fetch_log(), vec!["https://github.com/foo/bar.git"]); |
| 586 | /// ``` | 592 | /// ``` |
| 587 | pub struct MockSyncContext { | 593 | pub struct MockSyncContext { |
| 588 | /// Repository data to return from fetch_repository_data | 594 | /// Repository data to return from fetch_repository_data_with_purgatory |
| 589 | repo_data: RwLock<Option<RepositoryData>>, | 595 | repo_data: RwLock<Option<RepositoryData>>, |
| 590 | 596 | ||
| 591 | /// Clone URLs available for the repository (from announcements) | 597 | /// Clone URLs available for the repository (from announcements) |
| @@ -732,7 +738,10 @@ pub mod mock { | |||
| 732 | self.pr_clone_urls.clone() | 738 | self.pr_clone_urls.clone() |
| 733 | } | 739 | } |
| 734 | 740 | ||
| 735 | async fn fetch_repository_data(&self, _identifier: &str) -> Result<RepositoryData> { | 741 | async fn fetch_repository_data_with_purgatory( |
| 742 | &self, | ||
| 743 | _identifier: &str, | ||
| 744 | ) -> Result<RepositoryData> { | ||
| 736 | // Return stored repo_data or create a minimal one with clone URLs | 745 | // Return stored repo_data or create a minimal one with clone URLs |
| 737 | if let Some(data) = self.repo_data.read().unwrap().as_ref() { | 746 | if let Some(data) = self.repo_data.read().unwrap().as_ref() { |
| 738 | // Clone the data - this is a test mock so efficiency isn't critical | 747 | // Clone the data - this is a test mock so efficiency isn't critical |
diff --git a/src/purgatory/sync/functions.rs b/src/purgatory/sync/functions.rs index 9207d58..bd5c0c0 100644 --- a/src/purgatory/sync/functions.rs +++ b/src/purgatory/sync/functions.rs | |||
| @@ -104,7 +104,7 @@ pub async fn sync_identifier_next_url<C: SyncContext + ?Sized>( | |||
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | // 3. Get repository data | 106 | // 3. Get repository data |
| 107 | let repo_data = match ctx.fetch_repository_data(identifier).await { | 107 | let repo_data = match ctx.fetch_repository_data_with_purgatory(identifier).await { |
| 108 | Ok(data) => data, | 108 | Ok(data) => data, |
| 109 | Err(e) => { | 109 | Err(e) => { |
| 110 | debug!( | 110 | debug!( |
| @@ -228,7 +228,7 @@ pub async fn get_throttled_domains_with_untried_urls<C: SyncContext + ?Sized>( | |||
| 228 | throttle_manager: &ThrottleManager, | 228 | throttle_manager: &ThrottleManager, |
| 229 | git_naughty_list: &NaughtyListTracker, | 229 | git_naughty_list: &NaughtyListTracker, |
| 230 | ) -> Vec<ThrottledDomainInfo> { | 230 | ) -> Vec<ThrottledDomainInfo> { |
| 231 | let repo_data = match ctx.fetch_repository_data(identifier).await { | 231 | let repo_data = match ctx.fetch_repository_data_with_purgatory(identifier).await { |
| 232 | Ok(data) => data, | 232 | Ok(data) => data, |
| 233 | Err(_) => return vec![], | 233 | Err(_) => return vec![], |
| 234 | }; | 234 | }; |
| @@ -333,7 +333,7 @@ pub async fn sync_identifier_from_url<C: SyncContext + ?Sized>( | |||
| 333 | }; | 333 | }; |
| 334 | 334 | ||
| 335 | // Get repository data for target repo path | 335 | // Get repository data for target repo path |
| 336 | let repo_data = match ctx.fetch_repository_data(identifier).await { | 336 | let repo_data = match ctx.fetch_repository_data_with_purgatory(identifier).await { |
| 337 | Ok(data) => data, | 337 | Ok(data) => data, |
| 338 | Err(e) => { | 338 | Err(e) => { |
| 339 | debug!( | 339 | debug!( |