mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
rename sunc_bootstrap_relay_url
This commit is contained in:
+37
-4
@@ -99,13 +99,46 @@
|
||||
# Options: error, warn, info, debug, trace
|
||||
# RUST_LOG=info
|
||||
|
||||
# ============================================================================
|
||||
# PROACTIVE SYNC (GRASP-02)
|
||||
# ============================================================================
|
||||
|
||||
# Bootstrap relay URL for initial sync (optional)
|
||||
# Additional relays are automatically discovered from repository announcements
|
||||
# that list our service domain.
|
||||
# CLI: --sync-bootstrap-relay-url <url>
|
||||
# Default: (none - relay discovery from stored announcements only)
|
||||
# NGIT_SYNC_BOOTSTRAP_RELAY_URL=wss://relay.example.com
|
||||
|
||||
# Maximum backoff time in seconds for sync relay reconnection
|
||||
# CLI: --sync-max-backoff-secs <seconds>
|
||||
# Default: 3600 (1 hour)
|
||||
# NGIT_SYNC_MAX_BACKOFF_SECS=3600
|
||||
|
||||
# Delay in seconds before running startup catchup
|
||||
# CLI: --sync-startup-delay-secs <seconds>
|
||||
# Default: 30
|
||||
# NGIT_SYNC_STARTUP_DELAY_SECS=30
|
||||
|
||||
# Delay in seconds before running reconnect catchup
|
||||
# CLI: --sync-reconnect-delay-secs <seconds>
|
||||
# Default: 10
|
||||
# NGIT_SYNC_RECONNECT_DELAY_SECS=10
|
||||
|
||||
# Number of days to look back for reconnect catchup
|
||||
# CLI: --sync-reconnect-lookback-days <days>
|
||||
# Default: 3
|
||||
# NGIT_SYNC_RECONNECT_LOOKBACK_DAYS=3
|
||||
|
||||
# Maximum startup jitter in milliseconds for sync connections
|
||||
# Set to 0 to disable jitter (useful for testing)
|
||||
# CLI: --sync-startup-jitter-ms <ms>
|
||||
# Default: 10000 (10 seconds)
|
||||
# NGIT_SYNC_STARTUP_JITTER_MS=10000
|
||||
|
||||
# ============================================================================
|
||||
# FUTURE/PLANNED OPTIONS (not yet implemented)
|
||||
# ============================================================================
|
||||
|
||||
# Proactive sync settings (GRASP-02)
|
||||
# NGIT_PROACTIVE_SYNC_ENABLED=true
|
||||
# NGIT_PROACTIVE_SYNC_INTERVAL_SECS=3600
|
||||
|
||||
# Archive mode (GRASP-05)
|
||||
# NGIT_ARCHIVE_MODE=false
|
||||
@@ -758,7 +758,8 @@ The implementation closely follows the design document with the following comple
|
||||
|
||||
#### Phase 1: Basic Sync (commit b167f1b)
|
||||
- [`SyncManager`](../../src/sync/manager.rs) - Main coordinator for proactive sync
|
||||
- Single relay sync via `NGIT_SYNC_RELAY_URL` configuration
|
||||
- Bootstrap relay sync via `NGIT_SYNC_BOOTSTRAP_RELAY_URL` configuration
|
||||
- Dynamic relay discovery from repository announcements that list our service
|
||||
- Event validation through existing [`Nip34WritePolicy`](../../src/nostr/builder.rs)
|
||||
|
||||
#### Phase 2: Three-Layer Filters (commit bf558b0)
|
||||
@@ -844,12 +845,14 @@ All configuration via environment variables or CLI flags:
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `NGIT_SYNC_RELAY_URL` | String | None | Primary sync relay URL |
|
||||
| `NGIT_SYNC_BOOTSTRAP_RELAY_URL` | String | None | Bootstrap relay URL for initial sync |
|
||||
| `NGIT_SYNC_MAX_BACKOFF_SECS` | u64 | 3600 | Max backoff delay (seconds) |
|
||||
| `NGIT_SYNC_STARTUP_DELAY_SECS` | u64 | 30 | Catchup delay after startup |
|
||||
| `NGIT_SYNC_RECONNECT_DELAY_SECS` | u64 | 10 | Catchup delay after reconnect |
|
||||
| `NGIT_SYNC_RECONNECT_LOOKBACK_DAYS` | u64 | 3 | Days to look back on reconnect |
|
||||
|
||||
**Note:** Additional relays are automatically discovered from repository announcements (kind 30617) that list our service domain. The bootstrap relay provides an initial sync source but is not required - sync will discover relays from stored announcements.
|
||||
|
||||
### Module Structure (As Implemented)
|
||||
|
||||
```
|
||||
|
||||
@@ -269,28 +269,29 @@ NGIT_DATABASE_BACKEND=lmdb
|
||||
|
||||
These options configure the proactive sync feature that synchronizes events from other relays.
|
||||
|
||||
#### `NGIT_SYNC_RELAY_URL`
|
||||
#### `NGIT_SYNC_BOOTSTRAP_RELAY_URL`
|
||||
|
||||
**Description:** URL of the primary relay to sync events from
|
||||
**Description:** URL of the bootstrap relay to initially sync events from
|
||||
**Type:** String (WebSocket URL)
|
||||
**Default:** None (sync disabled)
|
||||
**Default:** None (relay discovery only)
|
||||
**Required:** No
|
||||
|
||||
**Examples:**
|
||||
```bash
|
||||
# Sync from a public relay
|
||||
NGIT_SYNC_RELAY_URL=wss://relay.example.com
|
||||
NGIT_SYNC_BOOTSTRAP_RELAY_URL=wss://relay.example.com
|
||||
|
||||
# Sync from another GRASP relay
|
||||
NGIT_SYNC_RELAY_URL=wss://git.nostr.dev
|
||||
NGIT_SYNC_BOOTSTRAP_RELAY_URL=wss://git.nostr.dev
|
||||
|
||||
# Local testing
|
||||
NGIT_SYNC_RELAY_URL=ws://127.0.0.1:8081
|
||||
NGIT_SYNC_BOOTSTRAP_RELAY_URL=ws://127.0.0.1:8081
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- When set, enables proactive sync feature
|
||||
- The relay will discover additional relays from repository announcements
|
||||
- Bootstrap relay provides initial sync source on startup
|
||||
- Additional relays are **automatically discovered** from repository announcements that list our service
|
||||
- Even without a bootstrap relay, sync will discover relays from stored announcements
|
||||
- Synced events go through the same validation as directly-submitted events
|
||||
- Use WebSocket protocol (`ws://` or `wss://`)
|
||||
|
||||
|
||||
+6
-4
@@ -84,9 +84,10 @@ pub struct Config {
|
||||
#[arg(long = "metrics-top-n-repos", env = "NGIT_METRICS_TOP_N_REPOS", default_value_t = 10)]
|
||||
pub metrics_top_n_repos: usize,
|
||||
|
||||
/// URL of relay to sync kind 30617 events from (optional, enables proactive sync)
|
||||
#[arg(long, env = "NGIT_SYNC_RELAY_URL")]
|
||||
pub sync_relay_url: Option<String>,
|
||||
/// URL of bootstrap relay to sync from on startup (optional)
|
||||
/// Sync discovers additional relays from repository announcements that list our service
|
||||
#[arg(long, env = "NGIT_SYNC_BOOTSTRAP_RELAY_URL")]
|
||||
pub sync_bootstrap_relay_url: Option<String>,
|
||||
|
||||
/// Maximum backoff time in seconds for sync relay reconnection (default: 3600 = 1 hour)
|
||||
#[arg(long, env = "NGIT_SYNC_MAX_BACKOFF_SECS", default_value_t = 3600)]
|
||||
@@ -163,11 +164,12 @@ impl Config {
|
||||
metrics_enabled: true,
|
||||
metrics_connection_per_ip_abuse_threshold: 10,
|
||||
metrics_top_n_repos: 10,
|
||||
sync_relay_url: None,
|
||||
sync_bootstrap_relay_url: None,
|
||||
sync_max_backoff_secs: 3600,
|
||||
sync_startup_delay_secs: 30,
|
||||
sync_reconnect_delay_secs: 10,
|
||||
sync_reconnect_lookback_days: 3,
|
||||
sync_startup_jitter_ms: 10_000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -105,11 +105,12 @@ mod tests {
|
||||
metrics_enabled: true,
|
||||
metrics_connection_per_ip_abuse_threshold: 10,
|
||||
metrics_top_n_repos: 10,
|
||||
sync_relay_url: None,
|
||||
sync_bootstrap_relay_url: None,
|
||||
sync_max_backoff_secs: 3600,
|
||||
sync_startup_delay_secs: 30,
|
||||
sync_reconnect_delay_secs: 10,
|
||||
sync_reconnect_lookback_days: 3,
|
||||
sync_startup_jitter_ms: 10_000,
|
||||
};
|
||||
|
||||
let doc = RelayInformationDocument::from_config(&config);
|
||||
@@ -144,11 +145,12 @@ mod tests {
|
||||
metrics_enabled: true,
|
||||
metrics_connection_per_ip_abuse_threshold: 10,
|
||||
metrics_top_n_repos: 10,
|
||||
sync_relay_url: None,
|
||||
sync_bootstrap_relay_url: None,
|
||||
sync_max_backoff_secs: 3600,
|
||||
sync_startup_delay_secs: 30,
|
||||
sync_reconnect_delay_secs: 10,
|
||||
sync_reconnect_lookback_days: 3,
|
||||
sync_startup_jitter_ms: 10_000,
|
||||
};
|
||||
|
||||
let doc = RelayInformationDocument::from_config(&config);
|
||||
|
||||
+4
-4
@@ -52,17 +52,17 @@ async fn main() -> Result<()> {
|
||||
);
|
||||
|
||||
// Start SyncManager for proactive sync (Phase 2: multi-relay support, Phase 3: health tracking)
|
||||
// Even without initial sync_relay_url, SyncManager can discover relays from stored announcements
|
||||
// Even without bootstrap relay, SyncManager discovers relays from stored announcements
|
||||
let sync_manager = SyncManager::new(
|
||||
config.sync_relay_url.clone(),
|
||||
config.sync_bootstrap_relay_url.clone(),
|
||||
config.domain.clone(),
|
||||
relay_with_db.database.clone(),
|
||||
relay_with_db.write_policy.clone(),
|
||||
&config,
|
||||
);
|
||||
|
||||
if config.sync_relay_url.is_some() {
|
||||
info!("Starting proactive sync from: {:?}", config.sync_relay_url);
|
||||
if config.sync_bootstrap_relay_url.is_some() {
|
||||
info!("Starting proactive sync with bootstrap relay: {:?}", config.sync_bootstrap_relay_url);
|
||||
} else {
|
||||
info!("Proactive sync enabled (will discover relays from stored announcements)");
|
||||
}
|
||||
|
||||
+17
-16
@@ -60,8 +60,9 @@ fn get_sync_source_addr(bind_address: &str) -> SocketAddr {
|
||||
|
||||
/// Coordinates proactive sync from configured and discovered relays
|
||||
pub struct SyncManager {
|
||||
/// Initial relay URL to sync from (from config)
|
||||
initial_relay_url: Option<String>,
|
||||
/// Bootstrap relay URL for initial sync (from config)
|
||||
/// Additional relays are discovered from repository announcements that list our service
|
||||
bootstrap_relay_url: Option<String>,
|
||||
/// Our relay's domain (for filtering)
|
||||
relay_domain: String,
|
||||
/// Database for storing accepted events
|
||||
@@ -82,20 +83,20 @@ impl SyncManager {
|
||||
/// Create a new SyncManager
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `initial_relay_url` - Optional initial relay URL from config
|
||||
/// * `bootstrap_relay_url` - Optional bootstrap relay URL from config
|
||||
/// * `relay_domain` - Our relay's domain (used to exclude self from sync)
|
||||
/// * `database` - Shared database for storing events and querying announcements
|
||||
/// * `write_policy` - Write policy for validating synced events
|
||||
/// * `config` - Configuration for health tracking settings
|
||||
pub fn new(
|
||||
initial_relay_url: Option<String>,
|
||||
bootstrap_relay_url: Option<String>,
|
||||
relay_domain: String,
|
||||
database: SharedDatabase,
|
||||
write_policy: Nip34WritePolicy,
|
||||
config: &Config,
|
||||
) -> Self {
|
||||
Self {
|
||||
initial_relay_url,
|
||||
bootstrap_relay_url,
|
||||
relay_domain,
|
||||
database,
|
||||
write_policy,
|
||||
@@ -109,14 +110,14 @@ impl SyncManager {
|
||||
/// Create a new SyncManager with metrics
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `initial_relay_url` - Optional initial relay URL from config
|
||||
/// * `bootstrap_relay_url` - Optional bootstrap relay URL from config
|
||||
/// * `relay_domain` - Our relay's domain (used to exclude self from sync)
|
||||
/// * `database` - Shared database for storing events and querying announcements
|
||||
/// * `write_policy` - Write policy for validating synced events
|
||||
/// * `config` - Configuration for health tracking settings
|
||||
/// * `metrics` - Sync metrics for Prometheus
|
||||
pub fn with_metrics(
|
||||
initial_relay_url: Option<String>,
|
||||
bootstrap_relay_url: Option<String>,
|
||||
relay_domain: String,
|
||||
database: SharedDatabase,
|
||||
write_policy: Nip34WritePolicy,
|
||||
@@ -124,7 +125,7 @@ impl SyncManager {
|
||||
metrics: SyncMetrics,
|
||||
) -> Self {
|
||||
Self {
|
||||
initial_relay_url,
|
||||
bootstrap_relay_url,
|
||||
relay_domain,
|
||||
database,
|
||||
write_policy,
|
||||
@@ -137,14 +138,14 @@ impl SyncManager {
|
||||
|
||||
/// Create a SyncManager with a single relay URL (Phase 1 compatibility)
|
||||
pub fn with_single_relay(
|
||||
sync_relay_url: String,
|
||||
bootstrap_url: String,
|
||||
database: SharedDatabase,
|
||||
write_policy: Nip34WritePolicy,
|
||||
) -> Self {
|
||||
// Extract domain from URL for filtering
|
||||
let relay_domain = extract_domain_from_url(&sync_relay_url).unwrap_or_default();
|
||||
let relay_domain = extract_domain_from_url(&bootstrap_url).unwrap_or_default();
|
||||
Self {
|
||||
initial_relay_url: Some(sync_relay_url),
|
||||
bootstrap_relay_url: Some(bootstrap_url),
|
||||
relay_domain,
|
||||
database,
|
||||
write_policy,
|
||||
@@ -176,9 +177,9 @@ impl SyncManager {
|
||||
/// and processes incoming events. Runs indefinitely until cancelled.
|
||||
pub async fn run(self) {
|
||||
tracing::info!(
|
||||
"Starting SyncManager (domain: {}, initial relay: {:?})",
|
||||
"Starting SyncManager (domain: {}, bootstrap relay: {:?})",
|
||||
self.relay_domain,
|
||||
self.initial_relay_url
|
||||
self.bootstrap_relay_url
|
||||
);
|
||||
|
||||
// Create the filter service
|
||||
@@ -196,13 +197,13 @@ impl SyncManager {
|
||||
// Collect all relays to connect to
|
||||
let mut relays_to_connect: Vec<String> = Vec::new();
|
||||
|
||||
// Start with initial relay if configured
|
||||
if let Some(ref url) = self.initial_relay_url {
|
||||
// Start with bootstrap relay if configured
|
||||
if let Some(ref url) = self.bootstrap_relay_url {
|
||||
if !self.is_own_relay(url) {
|
||||
relays_to_connect.push(url.clone());
|
||||
active_relays.insert(url.clone());
|
||||
} else {
|
||||
tracing::info!("Skipping initial relay (is our own relay): {}", url);
|
||||
tracing::info!("Skipping bootstrap relay (is our own relay): {}", url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ impl TestRelay {
|
||||
Self::start_with_options(port, None).await
|
||||
}
|
||||
|
||||
/// Start relay with sync from another relay
|
||||
/// Start relay with sync from another relay (bootstrap relay)
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -57,12 +57,12 @@ impl TestRelay {
|
||||
/// source.stop().await;
|
||||
/// }
|
||||
/// ```
|
||||
pub async fn start_with_sync(sync_relay_url: &str) -> Self {
|
||||
Self::start_with_options(Self::find_free_port(), Some(sync_relay_url.to_string())).await
|
||||
pub async fn start_with_sync(bootstrap_relay_url: &str) -> Self {
|
||||
Self::start_with_options(Self::find_free_port(), Some(bootstrap_relay_url.to_string())).await
|
||||
}
|
||||
|
||||
/// Start relay with options
|
||||
async fn start_with_options(port: u16, sync_relay_url: Option<String>) -> Self {
|
||||
async fn start_with_options(port: u16, bootstrap_relay_url: Option<String>) -> Self {
|
||||
let bind_address = format!("127.0.0.1:{}", port);
|
||||
let url = format!("ws://127.0.0.1:{}", port);
|
||||
|
||||
@@ -97,9 +97,9 @@ impl TestRelay {
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null());
|
||||
|
||||
// Add sync relay URL if provided
|
||||
if let Some(ref sync_url) = sync_relay_url {
|
||||
cmd.env("NGIT_SYNC_RELAY_URL", sync_url);
|
||||
// Add bootstrap relay URL if provided
|
||||
if let Some(ref bootstrap_url) = bootstrap_relay_url {
|
||||
cmd.env("NGIT_SYNC_BOOTSTRAP_RELAY_URL", bootstrap_url);
|
||||
}
|
||||
|
||||
let process = cmd.spawn().expect("Failed to start relay process");
|
||||
|
||||
@@ -170,7 +170,7 @@ async fn test_sync_configuration_applied() {
|
||||
tokio::time::sleep(Duration::from_millis(300)).await;
|
||||
|
||||
// Both relays should be running
|
||||
// The sync relay has NGIT_SYNC_RELAY_URL set (verified by relay starting)
|
||||
// The sync relay has NGIT_SYNC_BOOTSTRAP_RELAY_URL set (verified by relay starting)
|
||||
|
||||
let client_source = Client::default();
|
||||
client_source
|
||||
|
||||
Reference in New Issue
Block a user