Better structure and logger

This commit is contained in:
2025-08-30 02:41:39 +02:00
parent 6797007526
commit 19c102a7e8
7 changed files with 124 additions and 14 deletions
Generated
+1
View File
@@ -1683,6 +1683,7 @@ name = "voxa-server"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"once_cell",
"serde", "serde",
"serde_json", "serde_json",
"wasmtime", "wasmtime",
+1
View File
@@ -5,6 +5,7 @@ edition = "2024"
[dependencies] [dependencies]
anyhow = "1.0.99" anyhow = "1.0.99"
once_cell = "1.21.3"
serde = { version = "1.0.219", features = ["serde_derive"] } serde = { version = "1.0.219", features = ["serde_derive"] }
serde_json = "1.0.143" serde_json = "1.0.143"
wasmtime = { version = "36.0.2", optional = true } wasmtime = { version = "36.0.2", optional = true }
+65 -8
View File
@@ -1,7 +1,11 @@
use std::path::Path; use std::{
net::TcpListener,
path::{Path, PathBuf},
};
#[cfg(feature = "loader")] #[cfg(feature = "loader")]
pub mod loader; pub mod loader;
pub mod logger;
pub mod macros; pub mod macros;
pub mod plugin; pub mod plugin;
pub mod vfs; pub mod vfs;
@@ -15,6 +19,13 @@ pub struct ServerConfig {
port: u16, port: u16,
} }
pub struct Server {
plugins: Vec<PluginInstance>,
root: PathBuf,
config: ServerConfig,
logger: logger::Logger,
}
impl Default for ServerConfig { impl Default for ServerConfig {
fn default() -> Self { fn default() -> Self {
Self { port: 7080 } Self { port: 7080 }
@@ -22,19 +33,65 @@ impl Default for ServerConfig {
} }
impl ServerConfig { impl ServerConfig {
pub fn start(&self, root: &Path) -> Result<()> { pub fn build(self, root: &Path) -> Server {
let mut plugins: Vec<PluginInstance> = Vec::new(); Server::new_config(root, self)
#[cfg(feature = "loader")] }
loader::load_plugins(&mut plugins, &root.join("./plugins"))?; }
self.start_with(plugins, root) impl Server {
pub fn new(root: &Path) -> Self {
Self {
plugins: Vec::new(),
root: root.to_path_buf(),
config: ServerConfig::default(),
logger: logger::Logger::new("Server"),
}
} }
pub fn start_with(&self, mut plugins: Vec<PluginInstance>, root: &Path) -> Result<()> { pub fn new_config(root: &Path, config: ServerConfig) -> Self {
for plugin in &mut plugins { Self {
plugins: Vec::new(),
root: root.to_path_buf(),
config,
logger: logger::Logger::new("Server"),
}
}
pub fn run(&mut self) -> Result<()> {
// Load plugins
#[cfg(feature = "loader")]
loader::load_plugins(&mut self.plugins, &self.root.join("./plugins"))?;
// Initialize plugins
for plugin in &mut self.plugins {
plugin.init(); plugin.init();
} }
// Start server
let listener = TcpListener::bind(format!("0.0.0.0:{}", self.config.port));
self.logger
.info(format!("Server listening 0.0.0.0:{}", self.config.port));
self.logger
.warn(format!("Server listening 0.0.0.0:{}", self.config.port));
self.logger
.error(format!("Server listening 0.0.0.0:{}", self.config.port));
for stream in listener?.incoming() {
match stream {
Ok(stream) => {
self.logger
.info(format!("New connection: {}", stream.peer_addr()?));
}
Err(e) => {
self.logger.error(format!("Connection failed: {}", e));
}
}
}
Ok(()) Ok(())
} }
pub fn add_plugin(&mut self, plugin: PluginInstance) {
self.plugins.push(plugin);
}
} }
+8 -4
View File
@@ -3,7 +3,11 @@ use std::path::Path;
use wasmtime::{Engine, Linker, Module, Store}; use wasmtime::{Engine, Linker, Module, Store};
use wasmtime_wasi::WasiCtxBuilder; use wasmtime_wasi::WasiCtxBuilder;
use crate::{PluginInstance, vfs}; use crate::{PluginInstance, logger, vfs};
logger! {
const LOGGER "Loader"
}
pub fn load_plugin(wasm_path: &Path) -> anyhow::Result<PluginInstance> { pub fn load_plugin(wasm_path: &Path) -> anyhow::Result<PluginInstance> {
let engine = Engine::default(); let engine = Engine::default();
@@ -30,17 +34,17 @@ pub fn load_plugins(arr: &mut Vec<PluginInstance>, path: &Path) -> crate::Result
let entry = entry?; let entry = entry?;
let path = entry.path(); let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some("wasm") { if path.extension().and_then(|s| s.to_str()) == Some("wasm") {
println!("Loading plugin: {:?}", path); LOGGER.info(format!("Loading plugin: {:?}", path));
match load_plugin(&path) { match load_plugin(&path) {
Ok(plugin) => { Ok(plugin) => {
arr.push(plugin); arr.push(plugin);
} }
Err(e) => eprintln!("Failed to load plugin {:?}: {}", path, e), Err(e) => LOGGER.error(format!("Failed to load plugin {:?}: {}", path, e)),
} }
} }
} }
} else { } else {
eprintln!("{:?} is not a directory", path); LOGGER.error(format!("{:?} is not a directory", path));
} }
Ok(()) Ok(())
+25
View File
@@ -0,0 +1,25 @@
use std::fmt::Display;
pub struct Logger {
name: String,
}
impl Logger {
pub fn new<T: Display>(name: T) -> Self {
Logger {
name: name.to_string(),
}
}
pub fn info<T: Display>(&self, message: T) {
println!("\x1b[32mINFO\x1b[0m ({}) › {}", self.name, message);
}
pub fn warn<T: Display>(&self, message: T) {
println!("\x1b[33mWARN\x1b[0m ({}) › {}", self.name, message);
}
pub fn error<T: Display>(&self, message: T) {
println!("\x1b[31mERROR\x1b[0m ({}) › {}", self.name, message);
}
}
+21
View File
@@ -13,3 +13,24 @@ macro_rules! export_plugin {
} }
}; };
} }
#[macro_export]
macro_rules! logger {
(const $i:ident $name:expr) => {
const $i: once_cell::sync::Lazy<$crate::logger::Logger> =
once_cell::sync::Lazy::new(|| $crate::logger::Logger::new($name));
};
($i:ident $name:expr) => {
const $i: once_cell::sync::Lazy<$crate::logger::Logger> =
once_cell::sync::Lazy::new(|| $crate::logger::Logger::new($name));
};
(const $name:expr) => {
once_cell::sync::Lazy::new(|| $crate::logger::Logger::new($name))
};
($name:expr) => {
$crate::logger::Logger::new($name)
};
}
+3 -2
View File
@@ -5,6 +5,7 @@ use voxa_server::{ServerConfig, vfs};
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let root = PathBuf::new(); let root = PathBuf::new();
let config: ServerConfig = vfs::read_config(&root.join("config.json"))?; let config: ServerConfig = vfs::read_config(&root.join("config.json"))?;
let mut server = config.build(&root);
config.start(&root) server.run()?;
Ok(())
} }