Better structure and logger
This commit is contained in:
Generated
+1
@@ -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",
|
||||||
|
|||||||
@@ -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 }
|
||||||
|
|||||||
+66
-9
@@ -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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_with(&self, mut plugins: Vec<PluginInstance>, root: &Path) -> Result<()> {
|
impl Server {
|
||||||
for plugin in &mut plugins {
|
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 new_config(root: &Path, config: ServerConfig) -> Self {
|
||||||
|
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
@@ -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(())
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user