diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-12-03 11:17:39 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-12-03 11:19:20 +0000 |
| commit | 57bc8cd9c021feaf08e139e8fb62800bc476068e (patch) | |
| tree | c62abdffb4c91999cae2f570597b9ac154c2e51d /src | |
| parent | 2f8ecd482077d82f2d1a937c7f979eaaa87a27b2 (diff) | |
improved settings cli flags > env vars > defaults
Diffstat (limited to 'src')
| -rw-r--r-- | src/config.rs | 223 | ||||
| -rw-r--r-- | src/http/landing.rs | 8 | ||||
| -rw-r--r-- | src/http/mod.rs | 4 | ||||
| -rw-r--r-- | src/http/nip11.rs | 12 | ||||
| -rw-r--r-- | src/main.rs | 18 | ||||
| -rw-r--r-- | src/nostr/builder.rs | 15 |
6 files changed, 215 insertions, 65 deletions
diff --git a/src/config.rs b/src/config.rs index 9b0d0b8..d095178 100644 --- a/src/config.rs +++ b/src/config.rs | |||
| @@ -1,74 +1,205 @@ | |||
| 1 | use anyhow::{Context, Result}; | 1 | use anyhow::Result; |
| 2 | use clap::{Parser, ValueEnum}; | ||
| 2 | use serde::{Deserialize, Serialize}; | 3 | use serde::{Deserialize, Serialize}; |
| 3 | use std::env; | ||
| 4 | 4 | ||
| 5 | /// Database backend type for the relay | 5 | /// Database backend type for the relay |
| 6 | #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] | 6 | #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default, ValueEnum)] |
| 7 | #[serde(rename_all = "lowercase")] | 7 | #[serde(rename_all = "lowercase")] |
| 8 | #[derive(Default)] | ||
| 9 | pub enum DatabaseBackend { | 8 | pub enum DatabaseBackend { |
| 10 | /// In-memory database (default, fastest, no persistence) | 9 | /// LMDB backend (persistent, general purpose) |
| 11 | #[default] | 10 | #[default] |
| 12 | Memory, | 11 | Lmdb, |
| 13 | /// NostrDB backend (persistent, optimized for Nostr) | 12 | /// NostrDB backend (persistent, optimized for Nostr) |
| 14 | NostrDb, | 13 | NostrDb, |
| 15 | /// LMDB backend (persistent, general purpose) | 14 | /// In-memory database (fastest, no persistence - uses temp directory for git data) |
| 16 | Lmdb, | 15 | Memory, |
| 17 | } | 16 | } |
| 18 | 17 | ||
| 19 | impl std::str::FromStr for DatabaseBackend { | 18 | impl std::fmt::Display for DatabaseBackend { |
| 20 | type Err = anyhow::Error; | 19 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 21 | 20 | match self { | |
| 22 | fn from_str(s: &str) -> Result<Self> { | 21 | Self::Memory => write!(f, "memory"), |
| 23 | match s.to_lowercase().as_str() { | 22 | Self::NostrDb => write!(f, "nostrdb"), |
| 24 | "memory" => Ok(Self::Memory), | 23 | Self::Lmdb => write!(f, "lmdb"), |
| 25 | "nostrdb" => Ok(Self::NostrDb), | ||
| 26 | "lmdb" => Ok(Self::Lmdb), | ||
| 27 | _ => Err(anyhow::anyhow!( | ||
| 28 | "Invalid database backend: {}. Valid options: memory, nostrdb, lmdb", | ||
| 29 | s | ||
| 30 | )), | ||
| 31 | } | 24 | } |
| 32 | } | 25 | } |
| 33 | } | 26 | } |
| 34 | 27 | ||
| 35 | #[derive(Debug, Clone, Serialize, Deserialize)] | 28 | /// ngit-grasp - A GRASP (Git Relays Authorized via Signed-Nostr Proofs) implementation |
| 29 | /// | ||
| 30 | /// Configuration is loaded with the following priority (highest to lowest): | ||
| 31 | /// 1. CLI flags (e.g., --domain example.com) | ||
| 32 | /// 2. Environment variables (e.g., NGIT_DOMAIN=example.com) | ||
| 33 | /// 3. .env file (loaded automatically if present) | ||
| 34 | /// 4. Built-in defaults | ||
| 35 | #[derive(Debug, Clone, Serialize, Deserialize, Parser)] | ||
| 36 | #[command(author, version, about, long_about = None)] | ||
| 37 | #[command(propagate_version = true)] | ||
| 36 | pub struct Config { | 38 | pub struct Config { |
| 39 | /// Domain where this instance is hosted (required, used in GRASP validation) | ||
| 40 | #[arg(long, env = "NGIT_DOMAIN")] | ||
| 37 | pub domain: String, | 41 | pub domain: String, |
| 38 | pub owner_npub: String, | 42 | |
| 39 | pub relay_name: String, | 43 | /// Owner's npub (optional, for relay info in NIP-11) |
| 44 | #[arg(long, env = "NGIT_OWNER_NPUB")] | ||
| 45 | pub owner_npub: Option<String>, | ||
| 46 | |||
| 47 | /// Relay name for NIP-11 information document (defaults to "${domain} grasp relay") | ||
| 48 | #[arg(long = "relay-name", env = "NGIT_RELAY_NAME")] | ||
| 49 | pub relay_name_override: Option<String>, | ||
| 50 | |||
| 51 | /// Relay description for NIP-11 information document | ||
| 52 | #[arg( | ||
| 53 | long, | ||
| 54 | env = "NGIT_RELAY_DESCRIPTION", | ||
| 55 | default_value = "Git Nostr Relay - a grasp implementation" | ||
| 56 | )] | ||
| 40 | pub relay_description: String, | 57 | pub relay_description: String, |
| 58 | |||
| 59 | /// Path to store Git repositories | ||
| 60 | #[arg(long, env = "NGIT_GIT_DATA_PATH", default_value = "./data/git")] | ||
| 41 | pub git_data_path: String, | 61 | pub git_data_path: String, |
| 62 | |||
| 63 | /// Path to store Nostr relay data | ||
| 64 | #[arg(long, env = "NGIT_RELAY_DATA_PATH", default_value = "./data/relay")] | ||
| 42 | pub relay_data_path: String, | 65 | pub relay_data_path: String, |
| 66 | |||
| 67 | /// Server bind address (IP:PORT) | ||
| 68 | #[arg(long, env = "NGIT_BIND_ADDRESS", default_value = "127.0.0.1:8080")] | ||
| 43 | pub bind_address: String, | 69 | pub bind_address: String, |
| 70 | |||
| 71 | /// Database backend type | ||
| 72 | #[arg(long, env = "NGIT_DATABASE_BACKEND", value_enum, default_value_t = DatabaseBackend::Lmdb)] | ||
| 44 | pub database_backend: DatabaseBackend, | 73 | pub database_backend: DatabaseBackend, |
| 45 | } | 74 | } |
| 46 | 75 | ||
| 47 | impl Config { | 76 | impl Config { |
| 48 | pub fn from_env() -> Result<Self> { | 77 | /// Load configuration from CLI args, environment variables, and defaults. |
| 49 | // Load .env file if present | 78 | /// |
| 79 | /// Priority (highest to lowest): | ||
| 80 | /// 1. CLI flags | ||
| 81 | /// 2. Environment variables | ||
| 82 | /// 3. .env file | ||
| 83 | /// 4. Built-in defaults | ||
| 84 | pub fn load() -> Result<Self> { | ||
| 85 | // Load .env file if present (before clap parses, so env vars are available) | ||
| 50 | dotenvy::dotenv().ok(); | 86 | dotenvy::dotenv().ok(); |
| 51 | 87 | ||
| 52 | // Parse database backend from environment | 88 | // Parse CLI args (clap automatically handles env var fallback) |
| 53 | let database_backend = env::var("NGIT_DATABASE_BACKEND") | 89 | let config = Self::parse(); |
| 54 | .ok() | 90 | |
| 55 | .and_then(|s| s.parse().ok()) | 91 | Ok(config) |
| 56 | .unwrap_or_default(); | 92 | } |
| 57 | 93 | ||
| 58 | Ok(Config { | 94 | /// Get relay name (defaults to "${domain} grasp relay" if not set) |
| 59 | domain: env::var("NGIT_DOMAIN").unwrap_or_else(|_| "localhost:8080".to_string()), | 95 | pub fn relay_name(&self) -> String { |
| 60 | owner_npub: env::var("NGIT_OWNER_NPUB").context("NGIT_OWNER_NPUB must be set")?, | 96 | self.relay_name_override |
| 61 | relay_name: env::var("NGIT_RELAY_NAME") | 97 | .clone() |
| 62 | .unwrap_or_else(|_| "ngit-grasp relay".to_string()), | 98 | .unwrap_or_else(|| format!("{} grasp relay", self.domain)) |
| 63 | relay_description: env::var("NGIT_RELAY_DESCRIPTION") | 99 | } |
| 64 | .unwrap_or_else(|_| "A GRASP-compliant Nostr relay for Git".to_string()), | 100 | |
| 65 | git_data_path: env::var("NGIT_GIT_DATA_PATH") | 101 | /// Get effective git data path |
| 66 | .unwrap_or_else(|_| "./data/git".to_string()), | 102 | /// Returns a temp directory when using memory backend, otherwise the configured path |
| 67 | relay_data_path: env::var("NGIT_RELAY_DATA_PATH") | 103 | pub fn effective_git_data_path(&self) -> String { |
| 68 | .unwrap_or_else(|_| "./data/relay".to_string()), | 104 | if self.database_backend == DatabaseBackend::Memory { |
| 69 | bind_address: env::var("NGIT_BIND_ADDRESS") | 105 | std::env::temp_dir() |
| 70 | .unwrap_or_else(|_| "127.0.0.1:8080".to_string()), | 106 | .join("ngit-grasp-git") |
| 71 | database_backend, | 107 | .to_string_lossy() |
| 72 | }) | 108 | .into_owned() |
| 109 | } else { | ||
| 110 | self.git_data_path.clone() | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | /// Create config for testing | ||
| 115 | #[cfg(test)] | ||
| 116 | pub fn for_testing() -> Self { | ||
| 117 | Self { | ||
| 118 | domain: "localhost:8080".to_string(), | ||
| 119 | owner_npub: Some("npub1test".to_string()), | ||
| 120 | relay_name_override: Some("test relay".to_string()), | ||
| 121 | relay_description: "test description".to_string(), | ||
| 122 | git_data_path: "./test_data/git".to_string(), | ||
| 123 | relay_data_path: "./test_data/relay".to_string(), | ||
| 124 | bind_address: "127.0.0.1:8080".to_string(), | ||
| 125 | database_backend: DatabaseBackend::Memory, | ||
| 126 | } | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | #[cfg(test)] | ||
| 131 | mod tests { | ||
| 132 | use super::*; | ||
| 133 | |||
| 134 | #[test] | ||
| 135 | fn test_default_values() { | ||
| 136 | let config = Config::for_testing(); | ||
| 137 | assert_eq!(config.domain, "localhost:8080"); | ||
| 138 | assert_eq!(config.bind_address, "127.0.0.1:8080"); | ||
| 139 | // for_testing() uses Memory, but the actual default is Lmdb | ||
| 140 | assert_eq!(config.database_backend, DatabaseBackend::Memory); | ||
| 141 | } | ||
| 142 | |||
| 143 | #[test] | ||
| 144 | fn test_lmdb_is_default() { | ||
| 145 | // Verify the actual default via the enum's Default trait | ||
| 146 | assert_eq!(DatabaseBackend::default(), DatabaseBackend::Lmdb); | ||
| 147 | } | ||
| 148 | |||
| 149 | #[test] | ||
| 150 | fn test_memory_backend_uses_temp_dir() { | ||
| 151 | let config = Config { | ||
| 152 | database_backend: DatabaseBackend::Memory, | ||
| 153 | ..Config::for_testing() | ||
| 154 | }; | ||
| 155 | let git_path = config.effective_git_data_path(); | ||
| 156 | assert!(git_path.contains("ngit-grasp-git")); | ||
| 157 | } | ||
| 158 | |||
| 159 | #[test] | ||
| 160 | fn test_lmdb_backend_uses_configured_path() { | ||
| 161 | let config = Config { | ||
| 162 | database_backend: DatabaseBackend::Lmdb, | ||
| 163 | git_data_path: "./my/git/path".to_string(), | ||
| 164 | relay_data_path: "./my/relay/path".to_string(), | ||
| 165 | ..Config::for_testing() | ||
| 166 | }; | ||
| 167 | assert_eq!(config.effective_git_data_path(), "./my/git/path"); | ||
| 168 | } | ||
| 169 | |||
| 170 | #[test] | ||
| 171 | fn test_database_backend_display() { | ||
| 172 | assert_eq!(DatabaseBackend::Memory.to_string(), "memory"); | ||
| 173 | assert_eq!(DatabaseBackend::NostrDb.to_string(), "nostrdb"); | ||
| 174 | assert_eq!(DatabaseBackend::Lmdb.to_string(), "lmdb"); | ||
| 175 | } | ||
| 176 | |||
| 177 | #[test] | ||
| 178 | fn test_relay_name_default() { | ||
| 179 | let config = Config { | ||
| 180 | domain: "example.com".to_string(), | ||
| 181 | relay_name_override: None, | ||
| 182 | ..Config::for_testing() | ||
| 183 | }; | ||
| 184 | assert_eq!(config.relay_name(), "example.com grasp relay"); | ||
| 185 | } | ||
| 186 | |||
| 187 | #[test] | ||
| 188 | fn test_relay_name_override() { | ||
| 189 | let config = Config { | ||
| 190 | domain: "example.com".to_string(), | ||
| 191 | relay_name_override: Some("My Custom Relay".to_string()), | ||
| 192 | ..Config::for_testing() | ||
| 193 | }; | ||
| 194 | assert_eq!(config.relay_name(), "My Custom Relay"); | ||
| 195 | } | ||
| 196 | |||
| 197 | #[test] | ||
| 198 | fn test_owner_npub_optional() { | ||
| 199 | let config = Config { | ||
| 200 | owner_npub: None, | ||
| 201 | ..Config::for_testing() | ||
| 202 | }; | ||
| 203 | assert!(config.owner_npub.is_none()); | ||
| 73 | } | 204 | } |
| 74 | } | 205 | } |
diff --git a/src/http/landing.rs b/src/http/landing.rs index b978851..f9fca5b 100644 --- a/src/http/landing.rs +++ b/src/http/landing.rs | |||
| @@ -282,7 +282,7 @@ pub fn get_html(config: &Config) -> String { | |||
| 282 | format!( | 282 | format!( |
| 283 | include_str!("../../templates/landing.html"), | 283 | include_str!("../../templates/landing.html"), |
| 284 | base_css = get_base_css(), | 284 | base_css = get_base_css(), |
| 285 | relay_name = config.relay_name, | 285 | relay_name = config.relay_name(), |
| 286 | relay_description = config.relay_description, | 286 | relay_description = config.relay_description, |
| 287 | version = get_version(), | 287 | version = get_version(), |
| 288 | curation = curation, | 288 | curation = curation, |
| @@ -357,7 +357,7 @@ pub fn get_generic_404_html(config: &Config, path: &str) -> String { | |||
| 357 | </body> | 357 | </body> |
| 358 | </html>"##, | 358 | </html>"##, |
| 359 | base_css = get_base_css(), | 359 | base_css = get_base_css(), |
| 360 | relay_name = config.relay_name, | 360 | relay_name = config.relay_name(), |
| 361 | path = path, | 361 | path = path, |
| 362 | version = get_version(), | 362 | version = get_version(), |
| 363 | footer_script = get_footer_script(), | 363 | footer_script = get_footer_script(), |
| @@ -456,7 +456,7 @@ pub fn get_404_html(config: &Config, npub: &str, identifier: &str) -> String { | |||
| 456 | </body> | 456 | </body> |
| 457 | </html>"##, | 457 | </html>"##, |
| 458 | base_css = get_base_css(), | 458 | base_css = get_base_css(), |
| 459 | relay_name = config.relay_name, | 459 | relay_name = config.relay_name(), |
| 460 | npub = npub, | 460 | npub = npub, |
| 461 | identifier = identifier, | 461 | identifier = identifier, |
| 462 | version = get_version(), | 462 | version = get_version(), |
| @@ -598,7 +598,7 @@ pub fn get_repo_html(config: &Config, npub: &str, identifier: &str) -> String { | |||
| 598 | </body> | 598 | </body> |
| 599 | </html>"##, | 599 | </html>"##, |
| 600 | base_css = get_base_css(), | 600 | base_css = get_base_css(), |
| 601 | relay_name = config.relay_name, | 601 | relay_name = config.relay_name(), |
| 602 | npub = npub, | 602 | npub = npub, |
| 603 | identifier = identifier, | 603 | identifier = identifier, |
| 604 | version = get_version(), | 604 | version = get_version(), |
diff --git a/src/http/mod.rs b/src/http/mod.rs index 4665281..8b1f687 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs | |||
| @@ -118,7 +118,7 @@ impl Service<Request<Incoming>> for HttpService { | |||
| 118 | let path = req.uri().path().to_string(); | 118 | let path = req.uri().path().to_string(); |
| 119 | let query = req.uri().query().map(|s| s.to_string()); | 119 | let query = req.uri().query().map(|s| s.to_string()); |
| 120 | let method = req.method().clone(); | 120 | let method = req.method().clone(); |
| 121 | let git_data_path = self.config.git_data_path.clone(); | 121 | let git_data_path = self.config.effective_git_data_path(); |
| 122 | let database = self.database.clone(); | 122 | let database = self.database.clone(); |
| 123 | 123 | ||
| 124 | // Handle OPTIONS preflight requests (CORS) | 124 | // Handle OPTIONS preflight requests (CORS) |
| @@ -427,7 +427,7 @@ pub async fn run_server( | |||
| 427 | let bind_addr: SocketAddr = config.bind_address.parse()?; | 427 | let bind_addr: SocketAddr = config.bind_address.parse()?; |
| 428 | 428 | ||
| 429 | tracing::info!("Starting HTTP server on {}", bind_addr); | 429 | tracing::info!("Starting HTTP server on {}", bind_addr); |
| 430 | tracing::info!("Relay name: {}", config.relay_name); | 430 | tracing::info!("Relay name: {}", config.relay_name()); |
| 431 | tracing::info!("Domain: {}", config.domain); | 431 | tracing::info!("Domain: {}", config.domain); |
| 432 | 432 | ||
| 433 | let listener = TcpListener::bind(&bind_addr).await?; | 433 | let listener = TcpListener::bind(&bind_addr).await?; |
diff --git a/src/http/nip11.rs b/src/http/nip11.rs index ecb9769..e6a1e46 100644 --- a/src/http/nip11.rs +++ b/src/http/nip11.rs | |||
| @@ -57,9 +57,9 @@ impl RelayInformationDocument { | |||
| 57 | /// Create NIP-11 relay information document from configuration | 57 | /// Create NIP-11 relay information document from configuration |
| 58 | pub fn from_config(config: &Config) -> Self { | 58 | pub fn from_config(config: &Config) -> Self { |
| 59 | Self { | 59 | Self { |
| 60 | name: config.relay_name.clone(), | 60 | name: config.relay_name(), |
| 61 | description: config.relay_description.clone(), | 61 | description: config.relay_description.clone(), |
| 62 | pubkey: Some(config.owner_npub.clone()), | 62 | pubkey: config.owner_npub.clone(), |
| 63 | contact: None, // Could be added to config if needed | 63 | contact: None, // Could be added to config if needed |
| 64 | supported_nips: vec![ | 64 | supported_nips: vec![ |
| 65 | 1, // NIP-01: Basic protocol flow | 65 | 1, // NIP-01: Basic protocol flow |
| @@ -98,8 +98,8 @@ mod tests { | |||
| 98 | fn test_relay_information_document_structure() { | 98 | fn test_relay_information_document_structure() { |
| 99 | let config = Config { | 99 | let config = Config { |
| 100 | domain: "relay.example.com".to_string(), | 100 | domain: "relay.example.com".to_string(), |
| 101 | owner_npub: "npub1test".to_string(), | 101 | owner_npub: Some("npub1test".to_string()), |
| 102 | relay_name: "Test Relay".to_string(), | 102 | relay_name_override: Some("Test Relay".to_string()), |
| 103 | relay_description: "A test relay".to_string(), | 103 | relay_description: "A test relay".to_string(), |
| 104 | git_data_path: "./data/git".to_string(), | 104 | git_data_path: "./data/git".to_string(), |
| 105 | relay_data_path: "./data/relay".to_string(), | 105 | relay_data_path: "./data/relay".to_string(), |
| @@ -128,8 +128,8 @@ mod tests { | |||
| 128 | fn test_relay_information_document_json() { | 128 | fn test_relay_information_document_json() { |
| 129 | let config = Config { | 129 | let config = Config { |
| 130 | domain: "relay.example.com".to_string(), | 130 | domain: "relay.example.com".to_string(), |
| 131 | owner_npub: "npub1test".to_string(), | 131 | owner_npub: Some("npub1test".to_string()), |
| 132 | relay_name: "Test Relay".to_string(), | 132 | relay_name_override: Some("Test Relay".to_string()), |
| 133 | relay_description: "A test relay".to_string(), | 133 | relay_description: "A test relay".to_string(), |
| 134 | git_data_path: "./data/git".to_string(), | 134 | git_data_path: "./data/git".to_string(), |
| 135 | relay_data_path: "./data/relay".to_string(), | 135 | relay_data_path: "./data/relay".to_string(), |
diff --git a/src/main.rs b/src/main.rs index 1f18ab2..f80e920 100644 --- a/src/main.rs +++ b/src/main.rs | |||
| @@ -2,7 +2,10 @@ use anyhow::Result; | |||
| 2 | use tracing::{info, Level}; | 2 | use tracing::{info, Level}; |
| 3 | use tracing_subscriber::FmtSubscriber; | 3 | use tracing_subscriber::FmtSubscriber; |
| 4 | 4 | ||
| 5 | use ngit_grasp::{config::Config, http, nostr}; | 5 | use ngit_grasp::{ |
| 6 | config::{Config, DatabaseBackend}, | ||
| 7 | http, nostr, | ||
| 8 | }; | ||
| 6 | 9 | ||
| 7 | #[tokio::main] | 10 | #[tokio::main] |
| 8 | async fn main() -> Result<()> { | 11 | async fn main() -> Result<()> { |
| @@ -14,10 +17,17 @@ async fn main() -> Result<()> { | |||
| 14 | 17 | ||
| 15 | info!("Starting ngit-grasp with nostr-relay-builder..."); | 18 | info!("Starting ngit-grasp with nostr-relay-builder..."); |
| 16 | 19 | ||
| 17 | // Load configuration | 20 | // Load configuration (priority: CLI flags > env vars > .env file > defaults) |
| 18 | let config = Config::from_env()?; | 21 | let config = Config::load()?; |
| 22 | |||
| 19 | info!("Configuration loaded: {}", config.bind_address); | 23 | info!("Configuration loaded: {}", config.bind_address); |
| 20 | info!("Git data directory: {}", config.git_data_path); | 24 | info!("Domain: {}", config.domain); |
| 25 | info!("Relay name: {}", config.relay_name()); | ||
| 26 | info!("Git data directory: {}", config.effective_git_data_path()); | ||
| 27 | if config.database_backend != DatabaseBackend::Memory { | ||
| 28 | info!("Relay data directory: {}", config.relay_data_path); | ||
| 29 | } | ||
| 30 | info!("Database backend: {}", config.database_backend); | ||
| 21 | 31 | ||
| 22 | // Create Nostr relay with NIP-34 validation | 32 | // Create Nostr relay with NIP-34 validation |
| 23 | // Returns both the relay and database for direct queries in handlers | 33 | // Returns both the relay and database for direct queries in handlers |
diff --git a/src/nostr/builder.rs b/src/nostr/builder.rs index eabb38f..904cba4 100644 --- a/src/nostr/builder.rs +++ b/src/nostr/builder.rs | |||
| @@ -1203,22 +1203,31 @@ pub fn create_relay(config: &Config) -> Result<RelayWithDatabase> { | |||
| 1203 | tracing::info!("Using LMDB backend at: {}", db_path.display()); | 1203 | tracing::info!("Using LMDB backend at: {}", db_path.display()); |
| 1204 | // Ensure the database directory exists | 1204 | // Ensure the database directory exists |
| 1205 | std::fs::create_dir_all(db_path).map_err(|e| { | 1205 | std::fs::create_dir_all(db_path).map_err(|e| { |
| 1206 | anyhow::anyhow!("Failed to create LMDB directory {}: {}", db_path.display(), e) | 1206 | anyhow::anyhow!( |
| 1207 | "Failed to create LMDB directory {}: {}", | ||
| 1208 | db_path.display(), | ||
| 1209 | e | ||
| 1210 | ) | ||
| 1207 | })?; | 1211 | })?; |
| 1208 | Arc::new(NostrLMDB::open(db_path).map_err(|e| { | 1212 | Arc::new(NostrLMDB::open(db_path).map_err(|e| { |
| 1209 | anyhow::anyhow!("Failed to open LMDB database at {}: {}", db_path.display(), e) | 1213 | anyhow::anyhow!( |
| 1214 | "Failed to open LMDB database at {}: {}", | ||
| 1215 | db_path.display(), | ||
| 1216 | e | ||
| 1217 | ) | ||
| 1210 | })?) | 1218 | })?) |
| 1211 | } | 1219 | } |
| 1212 | }; | 1220 | }; |
| 1213 | 1221 | ||
| 1214 | // Build relay with GRASP-01 validation | 1222 | // Build relay with GRASP-01 validation |
| 1215 | // Clone Arc for the write policy so both relay and policy can access the database | 1223 | // Clone Arc for the write policy so both relay and policy can access the database |
| 1224 | let git_data_path = config.effective_git_data_path(); | ||
| 1216 | let builder = RelayBuilder::default() | 1225 | let builder = RelayBuilder::default() |
| 1217 | .database(database.clone()) | 1226 | .database(database.clone()) |
| 1218 | .write_policy(Nip34WritePolicy::new( | 1227 | .write_policy(Nip34WritePolicy::new( |
| 1219 | &config.domain, | 1228 | &config.domain, |
| 1220 | database.clone(), | 1229 | database.clone(), |
| 1221 | &config.git_data_path, | 1230 | &git_data_path, |
| 1222 | )); | 1231 | )); |
| 1223 | 1232 | ||
| 1224 | tracing::info!( | 1233 | tracing::info!( |