mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
The catchup sync mechanism (reconnection with since filter) is implemented in src/sync/mod.rs handle_connect_or_reconnect(), but cannot be reliably integration tested with current infrastructure: - TestRelay uses in-memory database (events lost on stop) - No way to force WebSocket disconnection without stopping relay - Stopping syncing relay creates new instance (fresh sync, not catchup) Convert the skeleton test file to comprehensive documentation explaining: - How catchup sync works (since filter on reconnect) - The 15-minute quick reconnect window logic - Why integration testing is not feasible - Alternative approaches that could enable testing - Related tests that cover adjacent functionality
111 lines
4.8 KiB
Rust
111 lines
4.8 KiB
Rust
//! Catchup Sync - Documentation Only
|
|
//!
|
|
//! This file documents the catchup sync mechanism. No integration tests are included
|
|
//! because the functionality cannot be reliably tested with current test infrastructure.
|
|
//!
|
|
//! # What is Catchup Sync?
|
|
//!
|
|
//! Catchup sync ensures that when a relay's WebSocket connection to another relay drops
|
|
//! and reconnects, any events the source relay received during the disconnection are
|
|
//! fetched using a `since` filter based on the last connection timestamp.
|
|
//!
|
|
//! # Implementation Status: ✅ IMPLEMENTED
|
|
//!
|
|
//! The catchup sync mechanism is fully implemented in the sync module via:
|
|
//!
|
|
//! - [`handle_connect_or_reconnect()`](../../src/sync/mod.rs) - Detects reconnection and
|
|
//! applies appropriate sync strategy
|
|
//! - [`RelayState.last_connected`](../../src/sync/mod.rs) - Tracks when we last connected
|
|
//! to each relay
|
|
//! - [`filters::build_announcement_filter(since)`](../../src/sync/filters.rs) - Builds
|
|
//! Layer 1 filters with `since` timestamp
|
|
//! - [`filters::build_layer2_and_layer3_filters(since)`](../../src/sync/filters.rs) -
|
|
//! Builds Layer 2/3 filters with `since` timestamp
|
|
//!
|
|
//! ## Reconnection Logic
|
|
//!
|
|
//! When a relay reconnects to a source relay, the sync manager uses smart reconnection:
|
|
//!
|
|
//! | Scenario | Behavior |
|
|
//! |----------|----------|
|
|
//! | First connection ever | Full sync (no `since` filter) |
|
|
//! | Reconnect within 15 min | Quick reconnect with `since = last_connected - 15min` |
|
|
//! | Reconnect after >15 min | Full sync (clear state, treat as fresh connection) |
|
|
//!
|
|
//! The 15-minute buffer on the `since` filter accounts for clock drift and ensures
|
|
//! no events are missed at the boundary.
|
|
//!
|
|
//! # Why No Integration Tests?
|
|
//!
|
|
//! Testing catchup sync in integration tests is not feasible with current infrastructure:
|
|
//!
|
|
//! ## 1. Cannot Force WebSocket Disconnection
|
|
//!
|
|
//! The catchup mechanism is designed for same-process reconnection scenarios, such as:
|
|
//! - Network hiccup causing temporary disconnection
|
|
//! - Source relay temporarily unreachable
|
|
//! - WebSocket connection timeout
|
|
//!
|
|
//! Our [`TestRelay`](../common/relay.rs) fixture doesn't provide a way to force a
|
|
//! WebSocket disconnection without stopping the relay entirely.
|
|
//!
|
|
//! ## 2. Stopping a Relay Loses Events (In-Memory Database)
|
|
//!
|
|
//! `TestRelay` uses `NGIT_DATABASE_BACKEND=memory` for test isolation. If we stop
|
|
//! the source relay (to simulate disconnection), all events are lost. When a new
|
|
//! instance starts, there's nothing to "catch up" on.
|
|
//!
|
|
//! ## 3. Stopping the Syncing Relay Creates a New Instance
|
|
//!
|
|
//! If we stop the syncing relay and start a new one:
|
|
//! - `last_connected` is lost (in-memory state)
|
|
//! - New instance does a fresh full sync, not a `since`-filtered catchup
|
|
//! - This is correct behavior, but tests the bootstrap path, not catchup
|
|
//!
|
|
//! # Alternative Testing Approaches (Not Implemented)
|
|
//!
|
|
//! These could enable catchup testing but add significant complexity:
|
|
//!
|
|
//! 1. **Persistent database for source relay** - Use SQLite instead of in-memory,
|
|
//! allowing relay restart without data loss
|
|
//!
|
|
//! 2. **TestRelay restart capability** - Add `restart()` method that preserves the
|
|
//! same port and database path
|
|
//!
|
|
//! 3. **Network simulation** - Add ability to inject network failures between specific
|
|
//! relay pairs without stopping either relay
|
|
//!
|
|
//! 4. **Internal sync manager API** - Expose methods to force reconnection without
|
|
//! network-level disruption
|
|
//!
|
|
//! # Related Tests
|
|
//!
|
|
//! While catchup sync itself isn't directly tested, related functionality is covered:
|
|
//!
|
|
//! - [`bootstrap.rs`](bootstrap.rs) - Tests that a new relay syncs existing events
|
|
//! from a bootstrap relay (fresh full sync path)
|
|
//! - [`live_sync.rs`](live_sync.rs) - Tests real-time sync of new events after
|
|
//! connection is established
|
|
//! - [`discovery.rs`](discovery.rs) - Tests that relays discover each other via
|
|
//! repository announcements
|
|
//!
|
|
//! # Design Rationale
|
|
//!
|
|
//! The catchup mechanism prioritizes simplicity and correctness:
|
|
//!
|
|
//! - **Correctness over testing**: The `since` filter logic is straightforward and
|
|
//! uses well-tested nostr-sdk primitives. The risk of bugs is low.
|
|
//!
|
|
//! - **15-minute quick reconnect window**: Balances efficiency (avoid full resync for
|
|
//! brief outages) with simplicity (don't track complex state for long outages).
|
|
//!
|
|
//! - **Full sync fallback**: After 15 minutes, the relay does a complete resync.
|
|
//! This guarantees no events are missed, at the cost of redundant transfers.
|
|
//!
|
|
//! # See Also
|
|
//!
|
|
//! - [`src/sync/mod.rs`](../../src/sync/mod.rs) - Main sync module with reconnection logic
|
|
//! - [`src/sync/filters.rs`](../../src/sync/filters.rs) - Filter builders with `since` support
|
|
//! - [`src/sync/metrics.rs`](../../src/sync/metrics.rs) - Metrics tracking event sources
|
|
//! including `RECONNECT` for catchup events
|