parametrize port, address and store path

This commit is contained in:
JOLIMAITRE Matthieu 2024-08-04 17:53:25 +02:00
parent 5a021f9781
commit a07c61fdbf
2 changed files with 30 additions and 9 deletions

View file

@ -1,5 +1,6 @@
use std::{ use std::{
fmt::Write, fmt::Write,
path::PathBuf,
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
@ -22,6 +23,22 @@ use validator::{Validate, ValidationError};
mod common; mod common;
mod store; mod store;
#[derive(Debug, clap::Parser)]
/// Arbre
struct Cmd {
#[arg(short, long, default_value_t = 8200)]
/// Port on which th server will listen.
port: u16,
#[arg(short, long, default_value = "0.0.0.0")]
/// Hostname or address on which th server will listen.
address: String,
#[arg(short, long, default_value = "./store")]
/// Path to the directory to use as storage for topics.
store: PathBuf,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct MainState { struct MainState {
store: Arc<RwLock<Store>>, store: Arc<RwLock<Store>>,
@ -29,7 +46,13 @@ struct MainState {
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
let store = Store::open("./store")?; let Cmd {
address,
port,
store,
} = clap::Parser::parse();
let store = Store::open(store)?;
let store = Arc::new(RwLock::new(store)); let store = Arc::new(RwLock::new(store));
let state = MainState { store }; let state = MainState { store };
@ -42,7 +65,7 @@ async fn main() -> Result<()> {
.route("/", get(home)) .route("/", get(home))
.with_state(state); .with_state(state);
let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap(); let listener = TcpListener::bind((address, port)).await.unwrap();
let server = axum::serve(listener, app); let server = axum::serve(listener, app);
server.await?; server.await?;

View file

@ -1,18 +1,18 @@
use std::{ use std::{
fs::{self, OpenOptions}, fs::{self, OpenOptions},
io::{ErrorKind, Write}, io::{ErrorKind, Write},
path::PathBuf,
}; };
use anyhow::Result; use anyhow::Result;
#[derive(Debug)] #[derive(Debug)]
pub struct Store { pub struct Store {
path: String, path: PathBuf,
} }
impl Store { impl Store {
pub fn open(path: impl ToString) -> Result<Self> { pub fn open(path: PathBuf) -> Result<Self> {
let path = path.to_string();
fs::create_dir_all(&path)?; fs::create_dir_all(&path)?;
Ok(Self { path }) Ok(Self { path })
} }
@ -44,8 +44,7 @@ impl Store {
} }
pub fn get(&self, topic: &str) -> Result<Vec<String>> { pub fn get(&self, topic: &str) -> Result<Vec<String>> {
let base = &self.path; let path = self.path.join(topic);
let path = format!("{base}/{topic}");
let content = fs::read_to_string(path)?; let content = fs::read_to_string(path)?;
Ok(content.split(SEPARATOR).map(String::from).collect()) Ok(content.split(SEPARATOR).map(String::from).collect())
} }
@ -53,8 +52,7 @@ impl Store {
pub fn insert(&mut self, topic: &str, content: String) -> Result<()> { pub fn insert(&mut self, topic: &str, content: String) -> Result<()> {
let content = content.replace('\u{c}', " "); let content = content.replace('\u{c}', " ");
let content = content.trim(); let content = content.trim();
let base = &self.path; let path = self.path.join(topic);
let path = format!("{base}/{topic}");
match OpenOptions::new().append(true).create(false).open(&path) { match OpenOptions::new().append(true).create(false).open(&path) {
Ok(mut file) => write!(&mut file, "{SEPARATOR}\n{content}\n")?, Ok(mut file) => write!(&mut file, "{SEPARATOR}\n{content}\n")?,
Err(error) if error.kind() == ErrorKind::NotFound => drop(fs::write(path, content)), Err(error) if error.kind() == ErrorKind::NotFound => drop(fs::write(path, content)),