organix 0.1.3

Building organic application in rust, leveraging tokio and defining inter communication layer mechanism
Documentation
use std::{collections::HashMap, future::Future};
use tokio::runtime::Handle;

pub struct Runtimes {
    watchdog: Runtime,
    shared: Runtime,
    individuals: HashMap<&'static str, Runtime>,
}

#[derive(Debug)]
pub struct RuntimeConfig {
    pub thread_name: &'static str,
    pub io_driver: bool,
    pub time_driver: bool,
    pub core_threads: Option<usize>,
    pub max_threads: Option<usize>,
    pub thread_stack_size: Option<usize>,
}

pub struct Runtime {
    rt: tokio::runtime::Runtime,
    config: RuntimeConfig,
}

impl Runtimes {
    pub fn new() -> std::io::Result<Self> {
        let watchdog = Runtime::build(RuntimeConfig::watchdog())?;
        let shared = Runtime::build(RuntimeConfig::shared())?;

        Ok(Self {
            watchdog,
            shared,
            individuals: HashMap::new(),
        })
    }

    pub fn watchdog(&self) -> &Runtime {
        &self.watchdog
    }

    pub fn watchdog_mut(&mut self) -> &mut Runtime {
        &mut self.watchdog
    }

    pub fn shared(&self) -> &Runtime {
        &self.shared
    }

    pub fn shared_mut(&mut self) -> &mut Runtime {
        &mut self.shared
    }

    pub fn add(&mut self, rt: Runtime) {
        self.individuals.insert(rt.config.thread_name, rt);
    }

    pub fn individual(&self, k: &'static str) -> Option<&Runtime> {
        self.individuals.get(k)
    }

    pub fn individual_mut(&mut self, k: &'static str) -> Option<&mut Runtime> {
        self.individuals.get_mut(k)
    }
}

impl Runtime {
    pub fn build(config: RuntimeConfig) -> std::io::Result<Self> {
        let mut builder = tokio::runtime::Builder::new();

        builder.thread_name(config.thread_name);

        if config.io_driver {
            builder.enable_io();
        }

        if config.time_driver {
            builder.enable_time();
        }

        if let Some(core_threads) = config.core_threads {
            builder.core_threads(core_threads);
        }

        if let Some(max_threads) = config.max_threads {
            builder.max_threads(max_threads);
        }

        if let Some(thread_stack_size) = config.thread_stack_size {
            builder.thread_stack_size(thread_stack_size);
        }

        builder
            .threaded_scheduler()
            .build()
            .map(|rt| Self { rt, config })
    }

    pub fn handle(&self) -> &Handle {
        self.rt.handle()
    }

    pub fn block_on<F: Future>(&mut self, future: F) -> F::Output {
        self.rt.block_on(future)
    }

    pub fn config(&self) -> &RuntimeConfig {
        &self.config
    }
}

impl RuntimeConfig {
    pub fn new(thread_name: &'static str) -> Self {
        Self {
            thread_name,
            io_driver: false,
            time_driver: false,
            core_threads: None,
            max_threads: None,
            thread_stack_size: None,
        }
    }

    fn watchdog() -> Self {
        Self {
            thread_name: "watchdog",
            io_driver: false,
            time_driver: true,
            core_threads: None,
            max_threads: None,
            thread_stack_size: None,
        }
    }

    fn shared() -> Self {
        Self {
            thread_name: "shared",
            io_driver: true,
            time_driver: true,
            core_threads: None,
            max_threads: None,
            thread_stack_size: None,
        }
    }
}