feat: initialize project structure, modules and configurations

This commit is contained in:
0xcathiefish
2026-05-30 08:38:18 +00:00
commit aa80ac21ee
15 changed files with 778 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
pub mod module_a;
pub mod module_b;
pub mod structs;
pub use module_a::{ModuleA, ModuleAError};
pub use module_b::{ModuleB, ModuleBError};
pub use structs::SharedMessage;
+38
View File
@@ -0,0 +1,38 @@
use anyhow::{Context, Result};
use dotenvy::dotenv;
use nosync::{ModuleA, ModuleB};
use std::env;
use tracing::info;
use tracing_subscriber::{EnvFilter, FmtSubscriber};
#[tokio::main]
async fn main() -> Result<()> {
// Load environment variables from .env if present
let _ = dotenv();
// Initialize tracing subscriber with settings from environment (RUST_LOG)
let subscriber = FmtSubscriber::builder()
.with_env_filter(EnvFilter::from_default_env())
.finish();
tracing::subscriber::set_global_default(subscriber)
.map_err(|e| anyhow::anyhow!("failed to set global tracing subscriber: {e}"))?;
info!("Starting nosync application...");
// Retrieve APP_NAME from environment variables, defaulting if not found
let app_name = env::var("APP_NAME").unwrap_or_else(|_| "nosync-default".to_string());
info!(app_name = %app_name, "Environment configured");
// Initialize ModuleA and ModuleB
let module_a = ModuleA::new(app_name).context("Failed to initialize ModuleA")?;
let module_b = ModuleB::new(module_a).context("Failed to initialize ModuleB")?;
// Run ModuleB logic
module_b
.run()
.await
.context("Error occurred during execution")?;
info!("nosync application finished successfully!");
Ok(())
}
+61
View File
@@ -0,0 +1,61 @@
use crate::structs::SharedMessage;
use thiserror::Error;
use tracing::{debug, info};
/// Errors specific to ModuleA.
#[derive(Error, Debug)]
pub enum ModuleAError {
#[error("Failed to process message: {0}")]
ProcessError(String),
}
/// ModuleA processes messages and manages a name field.
pub struct ModuleA {
name: String,
}
impl ModuleA {
/// Creates a new ModuleA instance.
pub fn new(name: String) -> Result<Self, ModuleAError> {
info!(name = %name, "Initializing ModuleA");
Ok(Self { name })
}
/// Processes a shared message asynchronously.
pub async fn process_message(&self, msg: SharedMessage) -> Result<String, ModuleAError> {
debug!(msg_id = msg.id, "Processing message in ModuleA");
if msg.content.is_empty() {
return Err(ModuleAError::ProcessError(
"Empty message content".to_string(),
));
}
Ok(format!("ModuleA[{}] processed: {}", self.name, msg.content))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_process_message_success() {
let module_a = ModuleA::new("test-a".to_string()).unwrap();
let msg = SharedMessage {
id: 42,
content: "Hello".to_string(),
};
let result = module_a.process_message(msg).await.unwrap();
assert_eq!(result, "ModuleA[test-a] processed: Hello");
}
#[tokio::test]
async fn test_process_message_empty_content() {
let module_a = ModuleA::new("test-a".to_string()).unwrap();
let msg = SharedMessage {
id: 42,
content: String::new(),
};
let result = module_a.process_message(msg).await;
assert!(result.is_err());
}
}
+48
View File
@@ -0,0 +1,48 @@
use crate::module_a::ModuleA;
use crate::structs::SharedMessage;
use thiserror::Error;
use tracing::info;
/// Errors specific to ModuleB.
#[derive(Error, Debug)]
pub enum ModuleBError {
#[error("ModuleA error occurred: {0}")]
AError(#[from] crate::module_a::ModuleAError),
}
/// ModuleB holds a reference to ModuleA and interacts with it.
pub struct ModuleB {
processor: ModuleA,
}
impl ModuleB {
/// Creates a new ModuleB instance by taking ownership of a ModuleA processor.
pub fn new(processor: ModuleA) -> Result<Self, ModuleBError> {
info!("Initializing ModuleB");
Ok(Self { processor })
}
/// Runs the business logic of ModuleB.
pub async fn run(&self) -> Result<(), ModuleBError> {
let msg = SharedMessage {
id: 100,
content: "Hello from ModuleB".to_string(),
};
let result = self.processor.process_message(msg).await?;
info!(result = %result, "ModuleB execution succeeded");
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_module_b_run() {
let module_a = ModuleA::new("test-a".to_string()).unwrap();
let module_b = ModuleB::new(module_a).unwrap();
let result = module_b.run().await;
assert!(result.is_ok());
}
}
+6
View File
@@ -0,0 +1,6 @@
/// Shared message structure across modules.
#[derive(Debug, Clone)]
pub struct SharedMessage {
pub id: u64,
pub content: String,
}