progress on overall structure

This commit is contained in:
Jolimaitre Matthieu 2021-11-12 21:01:35 +01:00
parent 5235ca9308
commit 3938b2032d
18 changed files with 272 additions and 58 deletions

18
Cargo.lock generated
View file

@ -59,6 +59,12 @@ dependencies = [
"tower-service",
]
[[package]]
name = "base64"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "bitflags"
version = "1.3.2"
@ -221,6 +227,7 @@ dependencies = [
"axum",
"chrono",
"colored",
"ron",
"serde",
"serde_json",
"sled",
@ -527,6 +534,17 @@ dependencies = [
"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]]
name = "ryu"
version = "1.0.5"

View file

@ -7,7 +7,7 @@ description = "Harmony server application"
[dependencies]
# async engine
tokio = { version = "1.0", features = ["full"] }
tokio = { version = "1.13.0", features = ["full"] }
# http client
axum = "0.3.2"
@ -16,9 +16,12 @@ axum = "0.3.2"
sled = "0.34.7"
# serialization
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.68"
serde = { version = "1.0.130", features = ["derive"] }
serde_json = "1.0.69"
# useful for logging
chrono = "0.4"
chrono = "0.4.19"
colored = "2.0.0"
# serialization format of config files
ron = "0.7.0"

4
config.ron Normal file
View file

@ -0,0 +1,4 @@
(
database_path: "./database",
port: 42069
)

4
database/conf Normal file
View file

@ -0,0 +1,4 @@
segment_size: 524288
use_compression: false
version: 0.34
v

BIN
database/db Normal file

Binary file not shown.

Binary file not shown.

View file

@ -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
///
#[derive(Clone, Serialize, Deserialize)]
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 {
/// try to read the configuration from local file or load default
pub fn read() -> Self {
todo!()
pub fn get() -> Self {
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
}
}
}

View file

@ -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
View 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
View 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,
}

View file

@ -1,33 +1,68 @@
use std::error;
use std::sync::{Arc, RwLock};
use super::config::Configuration;
use super::database::DbManager;
use super::db::DbManager;
use super::http::HttpManager;
use super::log::Logger;
///
/// main function
///
pub fn main() {
let configuration = Configuration::read();
pub async fn main() {
let configuration = Configuration::get();
let instance = Harsh::new(configuration);
instance.serve().await;
}
pub struct Harsh {
db_manager: DbManager,
logger: Logger,
http_manager: HttpManager,
pub shared_state: SharedState,
pub http_manager: HttpManager,
}
impl Harsh {
pub fn new(configuration: Configuration) -> Self {
let db_manager = DbManager::new(&configuration);
let logger = Logger::new(&configuration);
let http_manager = HttpManager::new();
let db_manager =
DbManager::new(configuration.clone()).expect("failed to open / create the database");
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 {
logger,
db_manager,
shared_state,
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>;

View file

@ -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
View 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
View 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
View 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>) {
//
}

View file

@ -11,7 +11,7 @@ pub struct Logger {
impl Logger {
/// adapt the static instance according to parameters specified by the configuration
pub fn new(_config: &Configuration) -> Self {
pub fn new(_config: Configuration) -> Self {
Logger {}
}

View file

@ -1,5 +1,24 @@
///
/// encapsulate the logic responsible for reading and parsing the server configuration
///
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;
///
/// encapsulate the logic responsible for receiving and routing http requests
///
pub mod http;
///
/// encapsulate the logic responsible for logging events occuring while the server is running
///
pub mod log;

View file

@ -1,6 +1,10 @@
///
/// library module
///
pub mod lib;
pub fn main() {
#[tokio::main]
pub async fn main() {
println!("Hello, harmony!");
lib::harsh::main();
lib::harsh::main().await;
}