removed bootstrapper and created config builder

This commit is contained in:
michael-bailey 2022-09-07 15:39:57 +01:00
parent 4bfaf1a813
commit 81f94e2a69
8 changed files with 73 additions and 179 deletions

View File

@ -1,95 +0,0 @@
use crate::bootstrapper::builder::Builder;
use crate::config_manager::ConfigManagerDataMessage::SoftSetValue;
use crate::config_manager::{ConfigManager, ConfigValue};
use crate::Server;
use actix::fut::wrap_future;
use actix::{
Actor, ActorFutureExt, ActorStreamExt, ActorTryFutureExt, Addr,
AsyncContext, Context,
};
use clap::ArgMatches;
use std::fs::OpenOptions;
use tokio::fs::File;
/// # Bootstrapper
/// This class acts as the init daemon of the server.
/// it creates the necessary actors required by the server before it inits.
/// it handles things like fetching configurations and uses them in server creation.
/// It takes the args passed into the program and overrides the corresponding fields in the config manager
pub struct Bootstrapper {
args: ArgMatches,
server: Option<Addr<Server>>,
}
impl Bootstrapper {
pub fn create() -> Builder {
Builder::new()
}
}
impl Actor for Bootstrapper {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
let config_file = self
.args
.get_one::<String>("config file")
.map(|v| v.clone());
let port = self.args.get_one::<u16>("port").map(|v| *v);
let name = self
.args
.get_one::<String>("server name")
.map(|v| v.clone());
let owner = self
.args
.get_one::<String>("server owner")
.map(|v| v.clone());
let fut = wrap_future(async move {
let config_manager = ConfigManager::shared(config_file);
if let Some(port) = port {
config_manager
.send(SoftSetValue(
"server.port".into(),
ConfigValue::Number(port.into()),
))
.await;
}
if let Some(name) = name {
let _ = config_manager
.send(SoftSetValue(
"server.name".into(),
ConfigValue::String(name),
))
.await;
}
if let Some(owner) = owner {
let _ = config_manager
.send(SoftSetValue(
"server.owner".into(),
ConfigValue::String(owner),
))
.await;
}
config_manager
})
.map(|val, obj: &mut Bootstrapper, _ctx| {
obj.server = Server::create(val).build().into();
});
ctx.spawn(fut);
}
}
impl From<Builder> for Bootstrapper {
fn from(b: Builder) -> Self {
Self {
args: b.args,
server: None,
}
}
}

View File

@ -1,33 +0,0 @@
use crate::{
bootstrapper::bootstrapper::Bootstrapper, config_manager::get_args,
};
use actix::{Actor, Addr};
use clap::ArgMatches;
use std::fs::OpenOptions;
use tokio::fs::File;
pub struct Builder {
pub(super) args: ArgMatches,
}
impl Builder {
pub(super) fn new() -> Self {
Self { args: get_args() }
}
pub fn file(mut self, path: String) -> Self {
let file = OpenOptions::new()
.create(true)
.write(true)
.read(true)
.open(path)
.ok()
.map(|val| File::from(val));
self
}
pub fn build(self) -> Addr<Bootstrapper> {
Bootstrapper::from(self).start()
}
}

View File

@ -1,5 +0,0 @@
mod bootstrapper;
mod builder;
mod messages;
pub(crate) use bootstrapper::Bootstrapper;

View File

@ -0,0 +1,29 @@
use actix::{Actor, Addr};
use crate::config_manager::ConfigManager;
pub(super) struct Builder {
pub(super) file_path: String,
}
impl Builder {
pub(super) fn new() -> Self {
Self {
file_path: "./config_file.toml".to_owned(),
}
}
#[allow(dead_code)]
pub fn config_path(mut self, path: impl Into<String>) -> Self {
self.file_path = path.into();
self
}
pub fn set_config_path(&mut self, path: impl Into<String>) {
self.file_path = path.into();
}
pub(super) fn build(self) -> Addr<ConfigManager> {
ConfigManager::from(self).start()
}
}

View File

@ -10,6 +10,7 @@ use toml::Value;
use crate::{
config_manager::{
builder::Builder,
get_args,
messages::{
ConfigManagerDataMessage, ConfigManagerDataResponse,
@ -23,6 +24,7 @@ use crate::{
static mut SHARED: Option<Addr<ConfigManager>> = None;
static INIT: Once = Once::new();
#[allow(dead_code)]
pub(crate) struct ConfigManager {
file: File,
stored: ConfigValue,
@ -30,58 +32,26 @@ pub(crate) struct ConfigManager {
subscribers: Vec<Recipient<ObservableMessage<ConfigManagerOutput>>>,
}
// static methods
impl ConfigManager {
pub fn shared(file: Option<String>) -> Addr<Self> {
pub fn shared() -> Addr<Self> {
INIT.call_once(|| {
// Since this access is inside a call_once, before any other accesses, it is safe
unsafe {
let mut file = Self::get_file();
let shared = Self::new(file);
let args = get_args();
let mut builder = Self::create();
SHARED = Some(shared);
}
args.get_one::<String>("config file")
.map(|p| builder.set_config_path(p));
unsafe { SHARED = Some(builder.build()) }
});
unsafe { SHARED.clone().unwrap() }
}
fn new(mut file: File) -> Addr<Self> {
let mut output = String::new();
file.read_to_string(&mut output)
.expect("failed to read from file");
let stored = output
.parse::<Value>()
.map(|v| v.into())
.ok()
.unwrap_or_else(|| ConfigValue::Dict(BTreeMap::new()));
let root = stored.clone();
Self {
file,
root,
stored,
subscribers: Vec::default(),
}
.start()
}
fn get_file() -> File {
let default = "./config_file.toml".to_owned();
let args = get_args();
let file_path =
args.get_one::<String>("config file").unwrap_or(&default);
OpenOptions::new()
.write(true)
.read(true)
.open(file_path)
.ok()
.unwrap()
pub(super) fn create() -> Builder {
Builder::new()
}
}
// instance methods
impl ConfigManager {
pub fn get_value(&self, key: String) -> Result<ConfigValue, &'static str> {
use ConfigValue::Dict;
@ -154,3 +124,31 @@ impl Handler<ConfigManagerDataMessage> for ConfigManager {
}
}
}
impl From<Builder> for ConfigManager {
fn from(builder: Builder) -> Self {
let mut file = OpenOptions::new()
.write(true)
.read(true)
.open(builder.file_path)
.ok()
.unwrap();
let mut output = String::new();
file.read_to_string(&mut output)
.expect("failed to read from file");
let stored = output
.parse::<Value>()
.map(|v| v.into())
.ok()
.unwrap_or_else(|| ConfigValue::Dict(BTreeMap::new()));
Self {
file,
root: stored.clone(),
stored,
subscribers: Vec::default(),
}
}
}

View File

@ -3,6 +3,7 @@
//! It tries to implement a singleton actor, that will be fetchable globaly.
mod arg_fetcher;
mod builder;
mod config_manager;
mod messages;
mod types;

View File

@ -3,7 +3,6 @@
//! It starts the actor runtime and then sleeps
//! for the duration of the program.
pub(crate) mod bootstrapper;
pub(crate) mod client_management;
pub(crate) mod config_manager;
pub(crate) mod lua;
@ -13,15 +12,15 @@ pub(crate) mod rhai;
pub(crate) mod scripting;
pub(crate) mod server;
use crate::bootstrapper::Bootstrapper;
use server::Server;
use tokio::time::{sleep, Duration};
use crate::config_manager::ConfigManager;
#[actix::main()]
async fn main() {
let init = Bootstrapper::create().build();
let init = Server::create(ConfigManager::shared()).build();
loop {
sleep(Duration::from_millis(1000)).await;
}