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:
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