nostr-rs-relay

My dev fork of nostr-rs-relay
git clone git://jb55.com/nostr-rs-relay
Log | Files | Refs | README | LICENSE

commit 5a19a8876f1eea3daf2faa567456178cac2a29e3
parent f7f12a7984f127e51a683e235b2a00df4e3ab4ee
Author: Greg Heartsfield <scsibug@imap.cc>
Date:   Fri, 31 Dec 2021 11:51:57 -0600

feat: allow database directory configuration

Adds configuration options for database directory, either on command
line through (--db dir-name) or the config.toml file.

Fixes: https://todo.sr.ht/~gheartsfield/nostr-rs-relay/13

Diffstat:
MDockerfile | 6++----
Mconfig.toml | 12++++++++----
Msrc/config.rs | 10++++++++++
Msrc/db.rs | 17++++++++++++-----
Msrc/error.rs | 2++
Msrc/main.rs | 26+++++++++++++++++++++++++-
6 files changed, 59 insertions(+), 14 deletions(-)

diff --git a/Dockerfile b/Dockerfile @@ -35,9 +35,7 @@ COPY --from=builder /nostr-rs-relay/target/release/nostr-rs-relay ${APP}/nostr-r RUN chown -R $APP_USER:$APP_USER ${APP} USER $APP_USER -WORKDIR ${APP_DATA} +WORKDIR ${APP} ENV RUST_LOG=info - - -CMD ["../nostr-rs-relay"] +CMD ["./nostr-rs-relay --db $APP_DATA"] diff --git a/config.toml b/config.toml @@ -1,4 +1,8 @@ # Nostr-rs-relay configuration +[database] +# Directory for SQLite files. Defaults to the current directory. Can +# also be specified with the "--db dirname" command line option. +data_directory = "data" [network] # Bind to this network address @@ -18,15 +22,15 @@ port = 8080 messages_per_sec = 0 # Maximum WebSocket message in bytes. Defaults to 128k. -#max_ws_message_bytes = 131072 +max_ws_message_bytes = 131072 # Maximum WebSocket frame size in bytes. Defaults to 128k. -#max_ws_frame_bytes = 131072 +max_ws_frame_bytes = 131072 # Broadcast buffer size, in number of events. This prevents slow # readers from consuming memory. Defaults to 4096. -#broadcast_buffer = 4096 +broadcast_buffer = 4096 # Event persistence buffer size, in number of events. This provides # backpressure to senders if writes are slow. Defaults to 16. -#event_persist_buffer = 16 +event_persist_buffer = 16 diff --git a/src/config.rs b/src/config.rs @@ -10,6 +10,12 @@ lazy_static! { #[derive(Debug, Serialize, Deserialize)] #[allow(unused)] +pub struct Database { + pub data_directory: String, +} + +#[derive(Debug, Serialize, Deserialize)] +#[allow(unused)] pub struct Network { pub port: u16, pub address: String, @@ -46,6 +52,7 @@ pub struct Limits { #[derive(Debug, Serialize, Deserialize)] #[allow(unused)] pub struct Settings { + pub database: Database, pub network: Network, pub limits: Limits, pub retention: Retention, @@ -82,6 +89,9 @@ impl Settings { impl Default for Settings { fn default() -> Self { Settings { + database: Database { + data_directory: ".".to_owned(), + }, network: Network { port: 8080, address: "0.0.0.0".to_owned(), diff --git a/src/db.rs b/src/db.rs @@ -122,14 +122,18 @@ pub async fn db_writer( mut shutdown: tokio::sync::broadcast::Receiver<()>, ) -> tokio::task::JoinHandle<Result<()>> { task::spawn_blocking(move || { + // get database configuration settings + let config = SETTINGS.read().unwrap(); + let db_dir = &config.database.data_directory; + let full_path = Path::new(db_dir).join(DB_FILE); + // create a connection let mut conn = Connection::open_with_flags( - Path::new(DB_FILE), + &full_path, OpenFlags::SQLITE_OPEN_READ_WRITE | OpenFlags::SQLITE_OPEN_CREATE, )?; - info!("opened database for writing"); + info!("opened database {:?} for writing", full_path); upgrade_db(&mut conn)?; // get rate limit settings - let config = SETTINGS.read().unwrap(); let rps_setting = config.limits.messages_per_sec; let mut lim_opt = None; let clock = governor::clock::QuantaClock::default(); @@ -373,9 +377,12 @@ pub async fn db_query( mut abandon_query_rx: tokio::sync::oneshot::Receiver<()>, ) { task::spawn_blocking(move || { + let config = SETTINGS.read().unwrap(); + let db_dir = &config.database.data_directory; + let full_path = Path::new(db_dir).join(DB_FILE); + let conn = - Connection::open_with_flags(Path::new(DB_FILE), OpenFlags::SQLITE_OPEN_READ_ONLY) - .unwrap(); + Connection::open_with_flags(&full_path, OpenFlags::SQLITE_OPEN_READ_ONLY).unwrap(); debug!("opened database for reading"); debug!("going to query for: {:?}", sub); // generate SQL query diff --git a/src/error.rs b/src/error.rs @@ -36,6 +36,8 @@ pub enum Error { SqlError(rusqlite::Error), #[error("Config error")] ConfigError(config::ConfigError), + #[error("Data directory does not exist")] + DatabaseDirError, } impl From<rusqlite::Error> for Error { diff --git a/src/main.rs b/src/main.rs @@ -12,6 +12,8 @@ use nostr_rs_relay::protostream; use nostr_rs_relay::protostream::NostrMessage::*; use nostr_rs_relay::protostream::NostrResponse::*; use std::collections::HashMap; +use std::env; +use std::path::Path; use tokio::net::{TcpListener, TcpStream}; use tokio::runtime::Builder; use tokio::sync::broadcast; @@ -20,17 +22,39 @@ use tokio::sync::mpsc; use tokio::sync::oneshot; use tungstenite::protocol::WebSocketConfig; +fn db_from_args(args: Vec<String>) -> Option<String> { + if args.len() == 3 { + if args.get(1) == Some(&"--db".to_owned()) { + return args.get(2).map(|x| x.to_owned()); + } + } + None +} + /// Start running a Nostr relay server. fn main() -> Result<(), Error> { // setup logger let _ = env_logger::try_init(); + // get database directory from args + let args: Vec<String> = env::args().collect(); + let db_dir: Option<String> = db_from_args(args); + info!("Using database: {:?}", db_dir); { let mut settings = config::SETTINGS.write().unwrap(); // replace default settings with those read from config.toml - let c = config::Settings::new(); + let mut c = config::Settings::new(); + // update with database location + if let Some(db) = db_dir { + c.database.data_directory = db.to_owned(); + } *settings = c; } let config = config::SETTINGS.read().unwrap(); + // do some config validation. + if !Path::new(&config.database.data_directory).is_dir() { + error!("Database directory does not exist"); + return Err(Error::DatabaseDirError); + } debug!("config: {:?}", config); let addr = format!("{}:{}", config.network.address.trim(), config.network.port); // configure tokio runtime