progress on overall structure
This commit is contained in:
parent
5235ca9308
commit
3938b2032d
18 changed files with 272 additions and 58 deletions
18
Cargo.lock
generated
18
Cargo.lock
generated
|
@ -59,6 +59,12 @@ dependencies = [
|
||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
|
@ -221,6 +227,7 @@ dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"chrono",
|
"chrono",
|
||||||
"colored",
|
"colored",
|
||||||
|
"ron",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sled",
|
"sled",
|
||||||
|
@ -527,6 +534,17 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ron"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b861ecaade43ac97886a512b360d01d66be9f41f3c61088b42cedf92e03d678"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"bitflags",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
|
|
11
Cargo.toml
11
Cargo.toml
|
@ -7,7 +7,7 @@ description = "Harmony server application"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
# async engine
|
# async engine
|
||||||
tokio = { version = "1.0", features = ["full"] }
|
tokio = { version = "1.13.0", features = ["full"] }
|
||||||
|
|
||||||
# http client
|
# http client
|
||||||
axum = "0.3.2"
|
axum = "0.3.2"
|
||||||
|
@ -16,9 +16,12 @@ axum = "0.3.2"
|
||||||
sled = "0.34.7"
|
sled = "0.34.7"
|
||||||
|
|
||||||
# serialization
|
# serialization
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0.130", features = ["derive"] }
|
||||||
serde_json = "1.0.68"
|
serde_json = "1.0.69"
|
||||||
|
|
||||||
# useful for logging
|
# useful for logging
|
||||||
chrono = "0.4"
|
chrono = "0.4.19"
|
||||||
colored = "2.0.0"
|
colored = "2.0.0"
|
||||||
|
|
||||||
|
# serialization format of config files
|
||||||
|
ron = "0.7.0"
|
||||||
|
|
4
config.ron
Normal file
4
config.ron
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
(
|
||||||
|
database_path: "./database",
|
||||||
|
port: 42069
|
||||||
|
)
|
4
database/conf
Normal file
4
database/conf
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
segment_size: 524288
|
||||||
|
use_compression: false
|
||||||
|
version: 0.34
|
||||||
|
vQÁ
|
BIN
database/db
Normal file
BIN
database/db
Normal file
Binary file not shown.
BIN
database/snap.0000000000000060
Normal file
BIN
database/snap.0000000000000060
Normal file
Binary file not shown.
|
@ -1,13 +1,61 @@
|
||||||
|
use std::fs::{read_to_string, write};
|
||||||
|
|
||||||
|
use ron;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::harsh::Error;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Encapsulate a configuration for the server
|
/// Encapsulate a configuration for the server
|
||||||
///
|
///
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
pub path: String, //
|
pub database_path: String, //
|
||||||
|
pub port: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CONFIG_PATHS: [&str; 2] = ["./config.ron", "/etc/harsh/harsh.ron"];
|
||||||
|
|
||||||
impl Configuration {
|
impl Configuration {
|
||||||
/// try to read the configuration from local file or load default
|
/// try to read the configuration from local file or load default
|
||||||
pub fn read() -> Self {
|
pub fn get() -> Self {
|
||||||
todo!()
|
match Self::try_from_file() {
|
||||||
|
Ok(config) => config,
|
||||||
|
Err(_) => {
|
||||||
|
let result = Configuration::default();
|
||||||
|
Configuration::write_config(&result);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_from_file() -> Result<Self, Error> {
|
||||||
|
let content = Self::try_read()?;
|
||||||
|
let config: Configuration = ron::from_str(&content)?;
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_read() -> Result<String, Error> {
|
||||||
|
for path in CONFIG_PATHS {
|
||||||
|
match read_to_string(path) {
|
||||||
|
Ok(serialized) => return Ok(serialized),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err("unable to locate or read config file".to_string().into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_config(data: &Self) {
|
||||||
|
let serialized = ron::to_string(data).unwrap();
|
||||||
|
write(CONFIG_PATHS[0], serialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Configuration {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
database_path: "./database".to_string(),
|
||||||
|
port: 42069, // haha funny number
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
use super::config::Configuration;
|
|
||||||
|
|
||||||
///
|
|
||||||
/// handle the database access
|
|
||||||
///
|
|
||||||
pub struct DbManager {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DbManager {
|
|
||||||
/// constructor
|
|
||||||
pub fn new(_config: &Configuration) -> Self {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
20
src/lib/db/mod.rs
Normal file
20
src/lib/db/mod.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
pub mod models;
|
||||||
|
|
||||||
|
use sled::Db;
|
||||||
|
|
||||||
|
use super::{config::Configuration, harsh::Error};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// handle the database access
|
||||||
|
///
|
||||||
|
pub struct DbManager {
|
||||||
|
handle: Db,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DbManager {
|
||||||
|
/// constructor
|
||||||
|
pub fn new(config: Configuration) -> Result<Self, Error> {
|
||||||
|
let handle = sled::open(config.database_path)?;
|
||||||
|
Ok(DbManager { handle })
|
||||||
|
}
|
||||||
|
}
|
18
src/lib/db/models.rs
Normal file
18
src/lib/db/models.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
type Id = u64;
|
||||||
|
|
||||||
|
pub struct User {
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
id: Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Channel {
|
||||||
|
name: String,
|
||||||
|
id: Id,
|
||||||
|
messages: Vec<Id>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Message {
|
||||||
|
content: String,
|
||||||
|
id: Id,
|
||||||
|
}
|
|
@ -1,33 +1,68 @@
|
||||||
|
use std::error;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use super::config::Configuration;
|
use super::config::Configuration;
|
||||||
use super::database::DbManager;
|
use super::db::DbManager;
|
||||||
use super::http::HttpManager;
|
use super::http::HttpManager;
|
||||||
use super::log::Logger;
|
use super::log::Logger;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// main function
|
/// main function
|
||||||
///
|
///
|
||||||
pub fn main() {
|
pub async fn main() {
|
||||||
let configuration = Configuration::read();
|
let configuration = Configuration::get();
|
||||||
|
let instance = Harsh::new(configuration);
|
||||||
|
instance.serve().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Harsh {
|
pub struct Harsh {
|
||||||
db_manager: DbManager,
|
pub shared_state: SharedState,
|
||||||
logger: Logger,
|
pub http_manager: HttpManager,
|
||||||
http_manager: HttpManager,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Harsh {
|
impl Harsh {
|
||||||
pub fn new(configuration: Configuration) -> Self {
|
pub fn new(configuration: Configuration) -> Self {
|
||||||
let db_manager = DbManager::new(&configuration);
|
let db_manager =
|
||||||
let logger = Logger::new(&configuration);
|
DbManager::new(configuration.clone()).expect("failed to open / create the database");
|
||||||
let http_manager = HttpManager::new();
|
let logger = Logger::new(configuration.clone());
|
||||||
|
let shared_state = State::new_shared(db_manager, logger);
|
||||||
|
let http_manager = HttpManager::new(configuration.clone(), shared_state.clone());
|
||||||
|
|
||||||
Harsh {
|
Harsh {
|
||||||
logger,
|
shared_state,
|
||||||
db_manager,
|
|
||||||
http_manager,
|
http_manager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serve(&mut self) {}
|
pub async fn serve(self) {
|
||||||
|
self.http_manager.serve().await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// shared state arround the app
|
||||||
|
///
|
||||||
|
pub struct State {
|
||||||
|
pub db_manager: RwLock<DbManager>,
|
||||||
|
pub logger: RwLock<Logger>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
pub fn new_shared(db_manager: DbManager, logger: Logger) -> SharedState {
|
||||||
|
let state = State {
|
||||||
|
db_manager: RwLock::new(db_manager),
|
||||||
|
logger: RwLock::new(logger),
|
||||||
|
};
|
||||||
|
Arc::new(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// safe pointer to the shared state
|
||||||
|
///
|
||||||
|
pub type SharedState = Arc<State>;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// error type for now..
|
||||||
|
///
|
||||||
|
pub type Error = Box<dyn error::Error>;
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
use super::config::Configuration;
|
|
||||||
use super::database::DbManager;
|
|
||||||
|
|
||||||
///
|
|
||||||
/// listen for incoming requests and handle both incoming and outgoing requests
|
|
||||||
///
|
|
||||||
pub struct HttpManager {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HttpManager {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
HttpManager {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// listen for and handle received requests
|
|
||||||
pub fn serve(_config: &Configuration, _db_manager: &mut DbManager) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
45
src/lib/http/mod.rs
Normal file
45
src/lib/http/mod.rs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
///
|
||||||
|
/// contains every route handlers
|
||||||
|
///
|
||||||
|
mod routes;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// contains every models used by the http server
|
||||||
|
///
|
||||||
|
pub mod models;
|
||||||
|
|
||||||
|
use axum::{AddExtensionLayer, Router};
|
||||||
|
|
||||||
|
use self::routes::setup_routes;
|
||||||
|
|
||||||
|
use super::config::Configuration;
|
||||||
|
use super::harsh::SharedState;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// listen for incoming requests and handle both incoming and outgoing requests
|
||||||
|
///
|
||||||
|
pub struct HttpManager {
|
||||||
|
_shared_state: SharedState,
|
||||||
|
app: Router,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HttpManager {
|
||||||
|
/// constructor
|
||||||
|
pub fn new(_config: Configuration, shared_state: SharedState) -> Self {
|
||||||
|
let app = setup_routes(Router::new()).layer(AddExtensionLayer::new(shared_state.clone()));
|
||||||
|
|
||||||
|
HttpManager {
|
||||||
|
_shared_state: shared_state.clone(),
|
||||||
|
app,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// listen for and handle received requests
|
||||||
|
pub async fn serve(self) {
|
||||||
|
let address = "0.0.0.0:3000".parse().unwrap();
|
||||||
|
axum::Server::bind(&address)
|
||||||
|
.serve(self.app.into_make_service())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
16
src/lib/http/models.rs
Normal file
16
src/lib/http/models.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct CreateUser {
|
||||||
|
name: String,
|
||||||
|
password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EditUser {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DeleteUser {
|
||||||
|
name: String,
|
||||||
|
password: String,
|
||||||
|
}
|
15
src/lib/http/routes.rs
Normal file
15
src/lib/http/routes.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use axum::extract::{Extension, Json};
|
||||||
|
use axum::routing::get;
|
||||||
|
use axum::Router;
|
||||||
|
|
||||||
|
use crate::lib::harsh::SharedState;
|
||||||
|
|
||||||
|
use super::models::*;
|
||||||
|
|
||||||
|
pub fn setup_routes(app: Router) -> Router {
|
||||||
|
app.route("/user/create", get(create_user))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_user(Extension(state): Extension<SharedState>, Json(payload): Json<CreateUser>) {
|
||||||
|
//
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ pub struct Logger {
|
||||||
|
|
||||||
impl Logger {
|
impl Logger {
|
||||||
/// adapt the static instance according to parameters specified by the configuration
|
/// adapt the static instance according to parameters specified by the configuration
|
||||||
pub fn new(_config: &Configuration) -> Self {
|
pub fn new(_config: Configuration) -> Self {
|
||||||
Logger {}
|
Logger {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,24 @@
|
||||||
|
///
|
||||||
|
/// encapsulate the logic responsible for reading and parsing the server configuration
|
||||||
|
///
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod database;
|
|
||||||
|
///
|
||||||
|
/// encapsulate the logic responsible for interacting with the database
|
||||||
|
///
|
||||||
|
pub mod db;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// main module, exposes the highest level structure holding the whole server runtime logic
|
||||||
|
///
|
||||||
pub mod harsh;
|
pub mod harsh;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// encapsulate the logic responsible for receiving and routing http requests
|
||||||
|
///
|
||||||
pub mod http;
|
pub mod http;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// encapsulate the logic responsible for logging events occuring while the server is running
|
||||||
|
///
|
||||||
pub mod log;
|
pub mod log;
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
|
///
|
||||||
|
/// library module
|
||||||
|
///
|
||||||
pub mod lib;
|
pub mod lib;
|
||||||
|
|
||||||
pub fn main() {
|
#[tokio::main]
|
||||||
|
pub async fn main() {
|
||||||
println!("Hello, harmony!");
|
println!("Hello, harmony!");
|
||||||
lib::harsh::main();
|
lib::harsh::main().await;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue