mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-06 07:28:23 +00:00
fix: detect NIP-77 NOTICE immediately during negentropy sync
Previously, when a relay didn't support NIP-77, the negentropy_sync_diff function would wait for the full client.sync() timeout even after receiving a NOTICE message that marked the relay as not supporting NIP-77. This change uses tokio::select! to race the sync operation against a polling task that checks the nip77_supported flag every 10ms. When a NOTICE is received (detected in the message handler), the poll task detects the status change and immediately returns an error, allowing quick fallback to REQ+EOSE without waiting for timeouts. Benefits: - Fast failure (within 10ms) when relay sends NIP-77 NOTICE - No artificial timeout reduction that could hurt legitimate operations - Maintains full timeout for relays that actually support NIP-77
This commit is contained in:
@@ -509,42 +509,65 @@ impl RelayConnection {
|
||||
// Use dry_run to only identify differences without downloading events
|
||||
let sync_opts = SyncOptions::default().dry_run();
|
||||
|
||||
match self.client.sync(filter.clone(), &sync_opts).await {
|
||||
Ok(output) => {
|
||||
let reconciliation = output.val;
|
||||
// Clone the atomic for the polling task
|
||||
let nip77_status = self.nip77_supported.clone();
|
||||
let url = self.url.clone();
|
||||
|
||||
// Create a polling task that checks if NIP-77 support was detected as unavailable
|
||||
let poll_task = async move {
|
||||
loop {
|
||||
let status = nip77_status.load(std::sync::atomic::Ordering::Relaxed);
|
||||
if status == 2 {
|
||||
// Relay confirmed not to support NIP-77 (via NOTICE or other means)
|
||||
return Err(format!(
|
||||
"Relay {} does not support NIP-77 (detected via NOTICE)",
|
||||
url
|
||||
));
|
||||
}
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
|
||||
}
|
||||
};
|
||||
|
||||
// Race the sync operation against the polling task
|
||||
let sync_task = self.client.sync(filter.clone(), &sync_opts);
|
||||
|
||||
let result = tokio::select! {
|
||||
poll_result = poll_task => {
|
||||
// Polling detected NIP-77 not supported
|
||||
poll_result
|
||||
}
|
||||
sync_result = sync_task => {
|
||||
// Sync completed (or failed) first
|
||||
match sync_result {
|
||||
Ok(output) => {
|
||||
// Check for any failures
|
||||
// Note: Timeouts are common for relays without NIP-77 support
|
||||
if !output.failed.is_empty() {
|
||||
Err(format!("Negentropy diff had failures: {:?}", output.failed))
|
||||
} else {
|
||||
Ok(output.val)
|
||||
}
|
||||
}
|
||||
Err(e) => Err(format!("Negentropy diff failed: {}", e))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(reconciliation) => {
|
||||
tracing::debug!(
|
||||
relay = %self.url,
|
||||
local_count = reconciliation.local.len(),
|
||||
remote_count = reconciliation.remote.len(),
|
||||
"Negentropy diff completed (dry run)"
|
||||
);
|
||||
|
||||
// Check for any failures
|
||||
// Note: Timeouts are common for relays without NIP-77 support
|
||||
if !output.failed.is_empty() {
|
||||
// Mark relay as not supporting NIP-77 (timeout typically means no support)
|
||||
self.nip77_supported
|
||||
.store(2, std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
// Log warning only once per relay to avoid spam
|
||||
if !self
|
||||
.nip77_warning_logged
|
||||
.swap(true, std::sync::atomic::Ordering::Relaxed)
|
||||
{
|
||||
tracing::warn!(
|
||||
relay = %self.url,
|
||||
failures = ?output.failed,
|
||||
"Negentropy diff had failures (timeout usually means relay doesn't support NIP-77), will fall back to REQ+EOSE"
|
||||
);
|
||||
}
|
||||
|
||||
return Err(format!("Negentropy diff had failures: {:?}", output.failed));
|
||||
}
|
||||
|
||||
Ok(reconciliation)
|
||||
}
|
||||
Err(e) => {
|
||||
// Mark relay as not supporting NIP-77
|
||||
self.nip77_supported
|
||||
.store(2, std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
// Log warning only once per relay to avoid spam
|
||||
if !self
|
||||
.nip77_warning_logged
|
||||
@@ -556,7 +579,7 @@ impl RelayConnection {
|
||||
"Negentropy diff failed, will fall back to REQ+EOSE"
|
||||
);
|
||||
}
|
||||
Err(format!("Negentropy diff failed: {}", e))
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user