Initial commit
This commit is contained in:
commit
8d32777f9f
8 changed files with 2790 additions and 0 deletions
96
src/main.rs
Normal file
96
src/main.rs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
mod config;
|
||||
mod db;
|
||||
mod error;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "mkv", about = "Distributed key-value store")]
|
||||
struct Cli {
|
||||
#[arg(short, long, default_value = "config.toml")]
|
||||
config: PathBuf,
|
||||
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
/// Start the index server
|
||||
Serve,
|
||||
/// Rebuild SQLite index from volume servers
|
||||
Rebuild,
|
||||
/// Rebalance data after adding/removing volumes
|
||||
Rebalance {
|
||||
#[arg(long)]
|
||||
dry_run: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
let cli = Cli::parse();
|
||||
let config = config::Config::load(&cli.config).unwrap_or_else(|e| {
|
||||
eprintln!("Failed to load config: {e}");
|
||||
std::process::exit(1);
|
||||
});
|
||||
|
||||
match cli.command {
|
||||
Commands::Serve => serve(config).await,
|
||||
Commands::Rebuild => {
|
||||
eprintln!("rebuild not yet implemented");
|
||||
std::process::exit(1);
|
||||
}
|
||||
Commands::Rebalance { dry_run: _ } => {
|
||||
eprintln!("rebalance not yet implemented");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn serve(config: config::Config) {
|
||||
let db_path = &config.database.path;
|
||||
|
||||
// Ensure parent directory exists
|
||||
if let Some(parent) = std::path::Path::new(db_path).parent() {
|
||||
std::fs::create_dir_all(parent).unwrap_or_else(|e| {
|
||||
eprintln!("Failed to create database directory: {e}");
|
||||
std::process::exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
let (writer, ready_rx) = db::spawn_writer(db_path.to_string());
|
||||
ready_rx.await.expect("writer failed to initialize");
|
||||
|
||||
let num_readers = std::thread::available_parallelism()
|
||||
.map(|n| n.get())
|
||||
.unwrap_or(4);
|
||||
let reads = db::ReadPool::new(db_path, num_readers);
|
||||
|
||||
let port = config.server.port;
|
||||
let volumes = config.volume_urls();
|
||||
|
||||
tracing::info!("Starting mkv server on port {port}");
|
||||
tracing::info!(" Readers: {num_readers}");
|
||||
tracing::info!(" Volumes: {volumes:?}");
|
||||
tracing::info!(
|
||||
" Replication factor: {}",
|
||||
config.server.replication_factor
|
||||
);
|
||||
|
||||
// TODO: wire up axum routes, volume client, hasher, health checker
|
||||
let app = axum::Router::new()
|
||||
.route("/health", axum::routing::get(|| async { "ok" }));
|
||||
|
||||
let addr = format!("0.0.0.0:{port}");
|
||||
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
||||
tracing::info!("Listening on {addr}");
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
|
||||
// Keep these alive (will be used in later phases)
|
||||
drop(writer);
|
||||
drop(reads);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue