diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-01-09 22:55:36 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-01-09 22:55:36 +0000 |
| commit | 615bfa0e3e892a22f1691a6a1172ea755a7c3149 (patch) | |
| tree | 2be46f2a647d5f9ba09d615dfd94c98ea6c9cfb0 /src/sync/relay_connection.rs | |
| parent | 953a4be45dda7477d3db8099722856eb11eb6bb2 (diff) | |
improve: detect and skip negentropy for unsupported relays
- Upgrade NOTICE log level to INFO when relay rejects negentropy (envelope/NEG- errors)
- Track NIP-77 support status per relay connection to avoid repeated failed attempts
- Mark relay as unsupported when NOTICE rejection or timeout occurs
- Skip negentropy on subsequent syncs during same connection session
- Reset support status on reconnect to allow retry after relay upgrades
This reduces log noise and eliminates 10-second timeout delays on each historic
sync attempt for relays that don't support NIP-77 negentropy.
Fixes negentropy-timeout-10-seconds issue by learning from relay behavior.
Diffstat (limited to 'src/sync/relay_connection.rs')
| -rw-r--r-- | src/sync/relay_connection.rs | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/src/sync/relay_connection.rs b/src/sync/relay_connection.rs index e57e06c..5fabd10 100644 --- a/src/sync/relay_connection.rs +++ b/src/sync/relay_connection.rs | |||
| @@ -76,6 +76,8 @@ pub struct RelayConnection { | |||
| 76 | database: Option<SharedDatabase>, | 76 | database: Option<SharedDatabase>, |
| 77 | /// Whether we've logged NIP-77 not supported for this relay (log once) | 77 | /// Whether we've logged NIP-77 not supported for this relay (log once) |
| 78 | nip77_warning_logged: std::sync::Arc<std::sync::atomic::AtomicBool>, | 78 | nip77_warning_logged: std::sync::Arc<std::sync::atomic::AtomicBool>, |
| 79 | /// Whether this relay supports NIP-77 negentropy (None = unknown, Some(false) = confirmed not supported) | ||
| 80 | nip77_supported: std::sync::Arc<std::sync::atomic::AtomicU8>, | ||
| 79 | } | 81 | } |
| 80 | 82 | ||
| 81 | impl RelayConnection { | 83 | impl RelayConnection { |
| @@ -115,6 +117,7 @@ impl RelayConnection { | |||
| 115 | client, | 117 | client, |
| 116 | database: None, | 118 | database: None, |
| 117 | nip77_warning_logged: std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)), | 119 | nip77_warning_logged: std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)), |
| 120 | nip77_supported: std::sync::Arc::new(std::sync::atomic::AtomicU8::new(0)), | ||
| 118 | } | 121 | } |
| 119 | } | 122 | } |
| 120 | 123 | ||
| @@ -132,6 +135,7 @@ impl RelayConnection { | |||
| 132 | client, | 135 | client, |
| 133 | database: Some(database), | 136 | database: Some(database), |
| 134 | nip77_warning_logged: std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)), | 137 | nip77_warning_logged: std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false)), |
| 138 | nip77_supported: std::sync::Arc::new(std::sync::atomic::AtomicU8::new(0)), | ||
| 135 | } | 139 | } |
| 136 | } | 140 | } |
| 137 | 141 | ||
| @@ -272,7 +276,25 @@ impl RelayConnection { | |||
| 272 | } | 276 | } |
| 273 | } | 277 | } |
| 274 | RelayMessage::Notice(msg) => { | 278 | RelayMessage::Notice(msg) => { |
| 275 | tracing::debug!(relay = %url, message = %msg, "Received NOTICE"); | 279 | // Check if this is a negentropy-related notice |
| 280 | let is_negentropy_notice = msg.contains("envelope") | ||
| 281 | || msg.contains("NEG-") | ||
| 282 | || msg.contains("negentropy"); | ||
| 283 | |||
| 284 | if is_negentropy_notice { | ||
| 285 | // Mark relay as not supporting NIP-77 | ||
| 286 | self.nip77_supported | ||
| 287 | .store(2, std::sync::atomic::Ordering::Relaxed); | ||
| 288 | |||
| 289 | tracing::info!( | ||
| 290 | relay = %url, | ||
| 291 | notice = %msg, | ||
| 292 | "Relay does not support NIP-77 (negentropy)" | ||
| 293 | ); | ||
| 294 | } else { | ||
| 295 | tracing::debug!(relay = %url, message = %msg, "Received NOTICE"); | ||
| 296 | } | ||
| 297 | |||
| 276 | let _ = | 298 | let _ = |
| 277 | event_sender.send(RelayEvent::Notice(msg.to_string())).await; | 299 | event_sender.send(RelayEvent::Notice(msg.to_string())).await; |
| 278 | // Don't break - continue processing events | 300 | // Don't break - continue processing events |
| @@ -427,7 +449,7 @@ impl RelayConnection { | |||
| 427 | 449 | ||
| 428 | /// Check if negentropy sync should be attempted | 450 | /// Check if negentropy sync should be attempted |
| 429 | /// | 451 | /// |
| 430 | /// Rather than relying on NIP-11 document detection (which can be unreliable), | 452 | /// For simplicity and robustness, we always try negentropy first. If it fails, |
| 431 | /// this returns true to indicate we should try negentropy sync. The actual | 453 | /// this returns true to indicate we should try negentropy sync. The actual |
| 432 | /// sync will handle failures gracefully with fallback to REQ+EOSE. | 454 | /// sync will handle failures gracefully with fallback to REQ+EOSE. |
| 433 | /// | 455 | /// |
| @@ -436,10 +458,23 @@ impl RelayConnection { | |||
| 436 | /// - Some relays support NIP-77 but don't advertise it in NIP-11 | 458 | /// - Some relays support NIP-77 but don't advertise it in NIP-11 |
| 437 | /// - Some relays claim NIP-77 support but have bugs | 459 | /// - Some relays claim NIP-77 support but have bugs |
| 438 | /// - The nostr-sdk 0.44 API for relay document access varies | 460 | /// - The nostr-sdk 0.44 API for relay document access varies |
| 461 | /// | ||
| 462 | /// # Returns | ||
| 463 | /// * `false` if we've confirmed this relay doesn't support NIP-77 | ||
| 464 | /// * `true` if unknown or supported (will attempt and handle failure) | ||
| 439 | pub async fn supports_negentropy(&self) -> bool { | 465 | pub async fn supports_negentropy(&self) -> bool { |
| 440 | // Always return true to attempt negentropy - we handle failure gracefully | 466 | // 0 = unknown (try it), 1 = supported, 2 = confirmed not supported |
| 441 | // in negentropy_sync_filter() which logs a warning and returns an error | 467 | let status = self |
| 442 | // that the caller can use to fall back to REQ+EOSE | 468 | .nip77_supported |
| 469 | .load(std::sync::atomic::Ordering::Relaxed); | ||
| 470 | |||
| 471 | if status == 2 { | ||
| 472 | // We've already confirmed this relay doesn't support NIP-77 | ||
| 473 | tracing::trace!(relay = %self.url, "Skipping negentropy - relay confirmed not to support NIP-77"); | ||
| 474 | return false; | ||
| 475 | } | ||
| 476 | |||
| 477 | // Unknown or supported - try it | ||
| 443 | true | 478 | true |
| 444 | } | 479 | } |
| 445 | 480 | ||
| @@ -488,6 +523,10 @@ impl RelayConnection { | |||
| 488 | // Check for any failures | 523 | // Check for any failures |
| 489 | // Note: Timeouts are common for relays without NIP-77 support | 524 | // Note: Timeouts are common for relays without NIP-77 support |
| 490 | if !output.failed.is_empty() { | 525 | if !output.failed.is_empty() { |
| 526 | // Mark relay as not supporting NIP-77 (timeout typically means no support) | ||
| 527 | self.nip77_supported | ||
| 528 | .store(2, std::sync::atomic::Ordering::Relaxed); | ||
| 529 | |||
| 491 | tracing::debug!( | 530 | tracing::debug!( |
| 492 | relay = %self.url, | 531 | relay = %self.url, |
| 493 | failures = ?output.failed, | 532 | failures = ?output.failed, |