State implementation and initial db work

State system is fully implemented and passing tests. I added in a
handful of unit tests to test most of the available operations.

Other work has involved getting the interface between client and server
right and starting on the actual message handler. This involves starting
work on the db as well
This commit is contained in:
2026-05-24 22:53:52 -07:00
parent c92ee309a9
commit eaeb293915
8 changed files with 1639 additions and 242 deletions
+29 -27
View File
@@ -6,7 +6,6 @@ mod state;
use diesel_async::pooled_connection::AsyncDieselConnectionManager;
use diesel_async::pooled_connection::deadpool::Pool;
use diesel_async::{AsyncConnection,AsyncPgConnection};
use quinn::rustls::pki_types::{PrivateKeyDer,CertificateDer,pem::PemObject};
use quinn::Endpoint;
use std::io;
@@ -21,25 +20,32 @@ use tokio::sync::{RwLock,broadcast,mpsc};
use crate::config::Config;
use crate::state::State;
use crate::state::{State,StateError};
#[derive(Hash,Eq,PartialEq,Clone,Serialize,Deserialize)]
#[derive(Hash,Eq,PartialEq,Clone,Serialize,Deserialize,Debug)]
pub struct Coordinate(Vec<i64>);
impl From<fedichat::RoomId> for Coordinate {
fn from(other: fedichat::RoomId) -> Coordinate {
Coordinate(other.coordinates)
}
}
#[tokio::main]
#[instrument]
async fn main() -> ExitCode {
// NOTE: This doesn't work as you can only initialize the global logger once
// Initial logger so we have something during config
tracing::subscriber::set_global_default(
tracing_subscriber::fmt().with_max_level(Level::WARN).finish()
).expect("Failed to setup logger");
//tracing::subscriber::set_global_default(
// tracing_subscriber::fmt().with_max_level(Level::WARN).finish()
//).expect("Failed to setup logger");
// Read in config
let config = match Config::load() {
Ok(c) => c,
Err(e) => {
error!("Problem while reading config file");
error!("{:?}",e);
eprintln!("Problem while reading config file");
eprintln!("{:?}",e);
return ExitCode::FAILURE;
}
};
@@ -54,7 +60,7 @@ async fn main() -> ExitCode {
"warn" => Level::WARN,
"error" => Level::ERROR,
_ => {
warn!("Invalid loglevel in config: {}",&loglevel);
eprintln!("Invalid loglevel in config: {}",&loglevel);
Level::INFO
},
}
@@ -120,29 +126,25 @@ async fn main() -> ExitCode {
let state = match State::load_from_file(&config.statefile) {
Ok(state) => state,
// Create file if it does not exist
Err(e) => {
match e.kind() {
io::ErrorKind::NotFound => {
match fs::File::create(&config.statefile) {
// If the statefile is writable then create an empty state
// and use that
Ok(_) => State::new(),
Err(e) => {
error!("Could not open or create statefile. Check your config.");
error!("{:?}",e);
return ExitCode::FAILURE;
}
}
},
_ => {
Err(StateError::IOError(e)) if e.kind() == io::ErrorKind::NotFound => {
match fs::File::create(&config.statefile) {
// If the statefile is writable then create an empty state
// and use that
Ok(_) => State::new(),
Err(e) => {
error!("Could not open or create statefile. Check your config.");
error!("{:?}",e);
return ExitCode::FAILURE;
}
}
},
Err(e) => {
error!("Could not open or create statefile. Check your config.");
error!("{:?}",e);
return ExitCode::FAILURE;
}
};
let statehandle = Arc::new(RwLock::new(state));
@@ -201,7 +203,7 @@ async fn main() -> ExitCode {
}
//Save state
match statehandle.write().await.write_to_file(&config.statefile) {
match statehandle.write().await.write_to_file(&config.statefile).await {
Ok(()) => debug!("Successfully wrote state to {:?}",config.statefile),
Err(e) => {
error!("Problem while writing to statefile");