diff options
Diffstat (limited to 'tests/sync/metrics.rs')
| -rw-r--r-- | tests/sync/metrics.rs | 139 |
1 files changed, 86 insertions, 53 deletions
diff --git a/tests/sync/metrics.rs b/tests/sync/metrics.rs index e8c75c7..e973bbb 100644 --- a/tests/sync/metrics.rs +++ b/tests/sync/metrics.rs | |||
| @@ -16,8 +16,8 @@ use nostr_sdk::prelude::*; | |||
| 16 | 16 | ||
| 17 | use crate::common::{ | 17 | use crate::common::{ |
| 18 | sync_helpers::{ | 18 | sync_helpers::{ |
| 19 | create_repo_announcement, fetch_metrics, wait_for_sync_connection, MetricsTestHarness, | 19 | create_repo_announcement, fetch_metrics, setup_announcement_on_relay, |
| 20 | ParsedMetrics, TestClient, | 20 | wait_for_sync_connection, MetricsTestHarness, ParsedMetrics, TestClient, |
| 21 | }, | 21 | }, |
| 22 | TestRelay, | 22 | TestRelay, |
| 23 | }; | 23 | }; |
| @@ -224,16 +224,17 @@ async fn test_startup_sync_event_count() { | |||
| 224 | // 3. Create test keys | 224 | // 3. Create test keys |
| 225 | let keys = Keys::generate(); | 225 | let keys = Keys::generate(); |
| 226 | 226 | ||
| 227 | // 4. Create an announcement that lists BOTH relays (required for discovery) | 227 | // 4. Set up announcement on SOURCE relay with git data |
| 228 | let announcement = create_repo_announcement( | 228 | // (purgatory requires git data before announcements are accepted) |
| 229 | &keys, | 229 | let repo_id = "test-repo-metrics"; |
| 230 | &[&source_relay.domain(), &syncing_relay.domain()], | 230 | let domains = vec![source_relay.domain(), syncing_relay.domain()]; |
| 231 | "test-repo-metrics", | 231 | let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); |
| 232 | ); | 232 | |
| 233 | let (announcement, _git_dir_source) = | ||
| 234 | setup_announcement_on_relay(&source_relay, &keys, &domain_refs, repo_id).await; | ||
| 233 | println!( | 235 | println!( |
| 234 | "Created announcement {} (kind {})", | 236 | "Announcement {} set up on source relay with git data", |
| 235 | announcement.id, | 237 | announcement.id |
| 236 | announcement.kind.as_u16() | ||
| 237 | ); | 238 | ); |
| 238 | 239 | ||
| 239 | // 5. Build the repo coordinate for the 'a' tag in the patches | 240 | // 5. Build the repo coordinate for the 'a' tag in the patches |
| @@ -241,7 +242,7 @@ async fn test_startup_sync_event_count() { | |||
| 241 | "{}:{}:{}", | 242 | "{}:{}:{}", |
| 242 | Kind::GitRepoAnnouncement.as_u16(), | 243 | Kind::GitRepoAnnouncement.as_u16(), |
| 243 | keys.public_key().to_hex(), | 244 | keys.public_key().to_hex(), |
| 244 | "test-repo-metrics" | 245 | repo_id |
| 245 | ); | 246 | ); |
| 246 | 247 | ||
| 247 | // 6. Create 3 patch events (Layer 2) that reference the announcement | 248 | // 6. Create 3 patch events (Layer 2) that reference the announcement |
| @@ -257,17 +258,11 @@ async fn test_startup_sync_event_count() { | |||
| 257 | .collect(); | 258 | .collect(); |
| 258 | println!("Created {} patches", patches.len()); | 259 | println!("Created {} patches", patches.len()); |
| 259 | 260 | ||
| 260 | // 7. Send announcement + patches to SOURCE relay ONLY | 261 | // 7. Send patches to SOURCE relay |
| 261 | let source_client = TestClient::new(source_relay.url(), keys.clone()) | 262 | let source_client = TestClient::new(source_relay.url(), keys.clone()) |
| 262 | .await | 263 | .await |
| 263 | .expect("Failed to connect to source relay"); | 264 | .expect("Failed to connect to source relay"); |
| 264 | 265 | ||
| 265 | source_client | ||
| 266 | .send_event(&announcement) | ||
| 267 | .await | ||
| 268 | .expect("Failed to send announcement to source"); | ||
| 269 | println!("Announcement sent to source relay"); | ||
| 270 | |||
| 271 | for patch in &patches { | 266 | for patch in &patches { |
| 272 | source_client | 267 | source_client |
| 273 | .send_event(patch) | 268 | .send_event(patch) |
| @@ -277,17 +272,10 @@ async fn test_startup_sync_event_count() { | |||
| 277 | println!("Patches sent to source relay"); | 272 | println!("Patches sent to source relay"); |
| 278 | source_client.disconnect().await; | 273 | source_client.disconnect().await; |
| 279 | 274 | ||
| 280 | // 8. Send announcement to SYNCING relay (triggers discovery of source relay) | 275 | // 8. Set up announcement on SYNCING relay (triggers discovery of source relay) |
| 281 | let syncing_client = TestClient::new(syncing_relay.url(), keys.clone()) | 276 | let (_announcement_syncing, _git_dir_syncing) = |
| 282 | .await | 277 | setup_announcement_on_relay(&syncing_relay, &keys, &domain_refs, repo_id).await; |
| 283 | .expect("Failed to connect to syncing relay"); | 278 | println!("Announcement set up on syncing relay (triggers discovery of source)"); |
| 284 | |||
| 285 | syncing_client | ||
| 286 | .send_event(&announcement) | ||
| 287 | .await | ||
| 288 | .expect("Failed to send announcement to syncing relay"); | ||
| 289 | println!("Announcement sent to syncing relay (triggers discovery of source)"); | ||
| 290 | syncing_client.disconnect().await; | ||
| 291 | 279 | ||
| 292 | // 9. Wait for discovery + sync to complete | 280 | // 9. Wait for discovery + sync to complete |
| 293 | println!("Waiting 5s for discovery and sync..."); | 281 | println!("Waiting 5s for discovery and sync..."); |
| @@ -404,18 +392,35 @@ async fn test_connection_failure_increments_counter() { | |||
| 404 | /// Test that live sync events are counted in metrics. | 392 | /// Test that live sync events are counted in metrics. |
| 405 | /// | 393 | /// |
| 406 | /// This test validates that events received via live subscription | 394 | /// This test validates that events received via live subscription |
| 407 | /// (after sync connection is established) are counted separately | 395 | /// (after sync connection is established) are counted in metrics. |
| 408 | /// from startup/bootstrap events. | 396 | /// Uses Layer 2 patch events (not announcements) to avoid purgatory, |
| 397 | /// since Layer 2 events are accepted directly to the DB. | ||
| 409 | #[tokio::test] | 398 | #[tokio::test] |
| 410 | async fn test_live_sync_event_count() { | 399 | async fn test_live_sync_event_count() { |
| 411 | let mut harness = MetricsTestHarness::with_sources(1).await; | ||
| 412 | |||
| 413 | // Pre-allocate syncing relay port to include in announcements | 400 | // Pre-allocate syncing relay port to include in announcements |
| 414 | let sync_port = TestRelay::find_free_port(); | 401 | let sync_port = TestRelay::find_free_port(); |
| 415 | let sync_domain = format!("127.0.0.1:{}", sync_port); | 402 | let sync_domain = format!("127.0.0.1:{}", sync_port); |
| 416 | 403 | ||
| 404 | // Start source relay | ||
| 405 | let source_relay = TestRelay::start().await; | ||
| 406 | println!("Source relay started at {}", source_relay.url()); | ||
| 407 | |||
| 408 | // Set up announcement on source relay BEFORE starting syncing relay | ||
| 409 | // This allows discovery when syncing relay connects | ||
| 410 | let keys = Keys::generate(); | ||
| 411 | let repo_id = "live-metrics-repo"; | ||
| 412 | let domains = vec![source_relay.domain(), sync_domain.clone()]; | ||
| 413 | let domain_refs: Vec<&str> = domains.iter().map(|s| s.as_str()).collect(); | ||
| 414 | |||
| 415 | let (_announcement, _git_dir) = | ||
| 416 | setup_announcement_on_relay(&source_relay, &keys, &domain_refs, repo_id).await; | ||
| 417 | println!("Announcement set up on source relay with git data"); | ||
| 418 | |||
| 417 | // Start syncing relay with pre-allocated port | 419 | // Start syncing relay with pre-allocated port |
| 418 | harness.start_syncing_relay_on_port(0, sync_port).await; | 420 | let syncing_relay = |
| 421 | TestRelay::start_on_port_with_options(sync_port, Some(source_relay.url().to_string()), false) | ||
| 422 | .await; | ||
| 423 | println!("Syncing relay started at {}", syncing_relay.url()); | ||
| 419 | 424 | ||
| 420 | // Wait for sync connection to be fully established with EOSE received | 425 | // Wait for sync connection to be fully established with EOSE received |
| 421 | // This ensures we're in "live" mode before submitting test events | 426 | // This ensures we're in "live" mode before submitting test events |
| @@ -424,33 +429,61 @@ async fn test_live_sync_event_count() { | |||
| 424 | .await | 429 | .await |
| 425 | .expect("Sync connection should be established"); | 430 | .expect("Sync connection should be established"); |
| 426 | 431 | ||
| 427 | // Additional small delay to ensure EOSE has been processed | 432 | // Additional delay to ensure purgatory promotion completes on syncing relay |
| 428 | tokio::time::sleep(Duration::from_millis(500)).await; | 433 | tokio::time::sleep(Duration::from_secs(4)).await; |
| 429 | 434 | ||
| 430 | // Now add events - these should be "live" not "startup" | 435 | // Now add Layer 2 patch events (not announcements) - these are accepted immediately |
| 431 | // Include BOTH domains so events are accepted by both relays | 436 | // (Layer 2 events are accepted directly to DB, no purgatory) |
| 432 | let keys = Keys::generate(); | 437 | let repo_coord_str = format!( |
| 433 | let events: Vec<_> = (0..2) | 438 | "{}:{}:{}", |
| 434 | .map(|i| { | 439 | Kind::GitRepoAnnouncement.as_u16(), |
| 435 | create_repo_announcement( | 440 | keys.public_key().to_hex(), |
| 436 | &keys, | 441 | repo_id |
| 437 | &[&harness.source_domain(0), &sync_domain], | 442 | ); |
| 438 | &format!("live-{}", i), | 443 | |
| 439 | ) | 444 | let patch1 = create_event_referencing_repo( |
| 440 | }) | 445 | &keys, |
| 441 | .collect(); | 446 | &repo_coord_str, |
| 442 | harness.submit_events(0, &events).await.unwrap(); | 447 | Kind::GitPatch.as_u16(), |
| 448 | "Live test patch 1", | ||
| 449 | ); | ||
| 450 | let patch2 = create_event_referencing_repo( | ||
| 451 | &keys, | ||
| 452 | &repo_coord_str, | ||
| 453 | Kind::GitPatch.as_u16(), | ||
| 454 | "Live test patch 2", | ||
| 455 | ); | ||
| 456 | |||
| 457 | // Send patches to source AFTER sync connection established (live mode) | ||
| 458 | let client = TestClient::new(source_relay.url(), keys.clone()) | ||
| 459 | .await | ||
| 460 | .expect("Failed to connect to source"); | ||
| 461 | client.send_event(&patch1).await.expect("Failed to send patch 1"); | ||
| 462 | client.send_event(&patch2).await.expect("Failed to send patch 2"); | ||
| 463 | client.disconnect().await; | ||
| 464 | println!("Two patches sent to source relay (live mode)"); | ||
| 443 | 465 | ||
| 444 | // Wait for live events to be processed and metrics updated | 466 | // Wait for live events to be processed and metrics updated |
| 445 | tokio::time::sleep(Duration::from_secs(4)).await; | 467 | tokio::time::sleep(Duration::from_secs(4)).await; |
| 446 | let metrics = harness.get_metrics().await.unwrap(); | 468 | |
| 469 | // Fetch metrics from syncing relay | ||
| 470 | let raw_metrics = fetch_metrics(&sync_url) | ||
| 471 | .await | ||
| 472 | .expect("Failed to fetch metrics"); | ||
| 473 | let metrics = ParsedMetrics::parse(&raw_metrics); | ||
| 447 | 474 | ||
| 448 | let synced_count = metrics.events_synced_total(); | 475 | let synced_count = metrics.events_synced_total(); |
| 449 | println!("Events synced total: {:?}", synced_count); | 476 | println!("Events synced total: {:?}", synced_count); |
| 450 | 477 | ||
| 451 | assert_eq!(synced_count, Some(2), "Should have 2 synced events"); | 478 | // Cleanup |
| 479 | syncing_relay.stop().await; | ||
| 480 | source_relay.stop().await; | ||
| 452 | 481 | ||
| 453 | harness.stop_all().await; | 482 | assert!( |
| 483 | synced_count.is_some() && synced_count.unwrap() >= 2, | ||
| 484 | "Should have synced at least 2 events, got {:?}", | ||
| 485 | synced_count | ||
| 486 | ); | ||
| 454 | } | 487 | } |
| 455 | 488 | ||
| 456 | /// Test that relay connected status is tracked in metrics. | 489 | /// Test that relay connected status is tracked in metrics. |