upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/purgatory/sync/context.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-01-10 02:14:01 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-01-10 02:15:22 +0000
commit1b6b669b9b82d1f81b887a32055f19c53d3bb8bf (patch)
tree3ce1785757cb3f16dfa30d74557042973d3bf53f /src/purgatory/sync/context.rs
parent730f430c906c6c2d43ea8f2e5fc3b408a3de128b (diff)
Add naughty list for git remotes with persistent SSL/DNS errors
Implement domain-level naughty list tracking for git remotes, reusing the existing NaughtyListTracker from relay sync. This prevents repeated attempts to fetch from git domains with persistent infrastructure issues (SSL/TLS certificate errors, DNS failures). Changes: - Updated NaughtyListTracker to track both relay URLs and git domains - Added git_naughty_list field to RealSyncContext for error classification - Modified fetch_oids() to classify git fetch errors and record naughty domains - Updated sync_identifier_next_url() to filter out naughty domains during URL selection - Added git_naughty_list parameter to ThrottleManager for domain queue processing - Threaded naughty list through start_sync_loop and all sync functions - Updated all tests to pass naughty list parameter The naughty list uses 12-hour expiration (configurable) to allow domains to recover from infrastructure issues. First occurrence logs WARN, repeats log DEBUG.
Diffstat (limited to 'src/purgatory/sync/context.rs')
-rw-r--r--src/purgatory/sync/context.rs38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/purgatory/sync/context.rs b/src/purgatory/sync/context.rs
index e61de01..3c2c683 100644
--- a/src/purgatory/sync/context.rs
+++ b/src/purgatory/sync/context.rs
@@ -187,6 +187,9 @@ use tracing::debug;
187use crate::nostr::builder::SharedDatabase; 187use crate::nostr::builder::SharedDatabase;
188use crate::nostr::events::RepositoryState; 188use crate::nostr::events::RepositoryState;
189use crate::purgatory::Purgatory; 189use crate::purgatory::Purgatory;
190use crate::sync::naughty_list::NaughtyListTracker;
191
192use super::functions::extract_domain;
190 193
191/// Real implementation of `SyncContext` that connects to actual systems. 194/// Real implementation of `SyncContext` that connects to actual systems.
192/// 195///
@@ -210,6 +213,9 @@ pub struct RealSyncContext {
210 213
211 /// Local relay for notifying WebSocket subscribers 214 /// Local relay for notifying WebSocket subscribers
212 local_relay: Option<LocalRelay>, 215 local_relay: Option<LocalRelay>,
216
217 /// Naughty list tracker for git remote domains with persistent errors
218 git_naughty_list: Arc<NaughtyListTracker>,
213} 219}
214 220
215impl RealSyncContext { 221impl RealSyncContext {
@@ -221,12 +227,14 @@ impl RealSyncContext {
221 /// * `git_data_path` - Base path for git repositories 227 /// * `git_data_path` - Base path for git repositories
222 /// * `our_domain` - Our domain to exclude from clone URLs 228 /// * `our_domain` - Our domain to exclude from clone URLs
223 /// * `local_relay` - Local relay for WebSocket notifications 229 /// * `local_relay` - Local relay for WebSocket notifications
230 /// * `git_naughty_list` - Naughty list tracker for git remote domains
224 pub fn new( 231 pub fn new(
225 purgatory: Arc<Purgatory>, 232 purgatory: Arc<Purgatory>,
226 database: SharedDatabase, 233 database: SharedDatabase,
227 git_data_path: PathBuf, 234 git_data_path: PathBuf,
228 our_domain: Option<String>, 235 our_domain: Option<String>,
229 local_relay: Option<LocalRelay>, 236 local_relay: Option<LocalRelay>,
237 git_naughty_list: Arc<NaughtyListTracker>,
230 ) -> Self { 238 ) -> Self {
231 Self { 239 Self {
232 purgatory, 240 purgatory,
@@ -234,8 +242,14 @@ impl RealSyncContext {
234 git_data_path, 242 git_data_path,
235 our_domain_value: our_domain, 243 our_domain_value: our_domain,
236 local_relay, 244 local_relay,
245 git_naughty_list,
237 } 246 }
238 } 247 }
248
249 /// Get reference to the git naughty list tracker
250 pub fn git_naughty_list(&self) -> &Arc<NaughtyListTracker> {
251 &self.git_naughty_list
252 }
239} 253}
240 254
241#[async_trait] 255#[async_trait]
@@ -344,6 +358,7 @@ impl SyncContext for RealSyncContext {
344 let repo_path = repo_path.to_path_buf(); 358 let repo_path = repo_path.to_path_buf();
345 let url = url.to_string(); 359 let url = url.to_string();
346 let missing_oids: Vec<String> = missing.into_iter().cloned().collect(); 360 let missing_oids: Vec<String> = missing.into_iter().cloned().collect();
361 let naughty_list = self.git_naughty_list.clone();
347 362
348 tokio::task::spawn_blocking(move || -> Result<Vec<String>> { 363 tokio::task::spawn_blocking(move || -> Result<Vec<String>> {
349 // git fetch <remote> <sha1> <sha2> ... - fetch all OIDs in one command 364 // git fetch <remote> <sha1> <sha2> ... - fetch all OIDs in one command
@@ -370,6 +385,29 @@ impl SyncContext for RealSyncContext {
370 } 385 }
371 Ok(result) => { 386 Ok(result) => {
372 let stderr = String::from_utf8_lossy(&result.stderr); 387 let stderr = String::from_utf8_lossy(&result.stderr);
388
389 // Extract domain and classify error for naughty list
390 if let Some(domain) = extract_domain(&url) {
391 if let Some(category) = NaughtyListTracker::classify_error(&stderr) {
392 let is_new = naughty_list.record(&domain, category, stderr.to_string());
393
394 if is_new {
395 tracing::warn!(
396 domain = %domain,
397 category = %category,
398 error = %stderr,
399 "Git remote domain added to naughty list"
400 );
401 } else {
402 debug!(
403 domain = %domain,
404 category = %category,
405 "Git remote domain still on naughty list"
406 );
407 }
408 }
409 }
410
373 Err(anyhow::anyhow!("git fetch failed: {}", stderr)) 411 Err(anyhow::anyhow!("git fetch failed: {}", stderr))
374 } 412 }
375 Err(e) => Err(anyhow::anyhow!("git fetch command error: {}", e)), 413 Err(e) => Err(anyhow::anyhow!("git fetch command error: {}", e)),