#service #manager #run-time #anthill #service-manager

anthill-service-system

Rust 运行时服务系统管理器,具有依赖注入集成

3 个稳定版本

1.2.3 2022年5月5日
1.1.1 2022年4月25日
1.0.2 2022年1月16日
0.1.1 2021年10月2日

#134 in #manager

MIT 许可证

51KB
922

build & tests

anthill-service-system

Rust 运行时服务系统管理器,具有 anthill-di 集成

所需的最小 anthill-di 版本 1.2.3

警告

该库需要 Rust nightly 才能使用 anthill-di


基本概念

首先你需要创建一个应用程序

async fn _() {
    // create new ioc context
    let mut app = Application::new().await;

    // -- or -- //

    // from exist ioc context
    let root_context = DependencyContext::new_root();
    root_context.register_type::<Application>(DependencyLifeCycle::Transient).await.unwrap();

    // On create Application created new ioc context
    let mut app = root_context.resolve::<Application>().await.unwrap();
}

服务必须实现 trait IBaseService + Constructor

#[async_trait]
impl IBaseService for TestHostedService1 {
    async fn on_start(&mut self) {
        // you have (by default) 5s
        // to do something on start
    }

    async fn on_stop(&mut self) {
        // you have (by default) 5s
        // to do something on stop
    }
}

或者你可以使用扩展在单独的任务中工作

#[async_trait]
impl IBackgroundService for TestBackgroundService1 {
    async fn execute(&self) {
        // you can do anything before app stoned
        // check state time by time and exit on stop (see next)
    }
}

为了操作应用程序状态,你可以请求一个依赖 Arc<dyn ILifeTimeManager>

async fn _(ctx: DependencyContext) {
    let app_lifetime = ctx.resolve::<Arc<dyn ILifeTimeManager>>().await.unwrap();

    // check app state
    let is_running = app_lifetime.is_running().await;

    // stop app
    app_lifetime.stop().await;

    // wait until app stop request
    app_lifetime.wait_for_stop().await;
}

然后注册依赖和服务


async fn _() {
    // let mut app = Application::new().await;

    // for mor info about ioc see (https://crates.io/crates/anthill-di)
    app.root_ioc_context.register_type::<SomeType>(DependencyLifeCycle::Transient).await.unwrap();

    app.register_service::<BackgroundService<TestBackgroundService>>().await.unwrap();

    app.register_service::<TestBaseService>().await.unwrap();
}

为了更方便地设置服务,使用 IStartup

#[async_trait]
impl IStartup for TestStartup {
async fn configure_dependency(&mut self, root_ioc_context: &mut DependencyContext) {
        root_ioc_context.register_type::<SomeComponent>().await.unwrap();
    }

    async fn configure_application(&mut self, _ : Arc<RwLock<CoreConfig>>, app: &mut Application) {
        app.register_service::<BackgroundService<TestBackgroundService1>>().await.unwrap();
        app.register_service::<BackgroundService<TestBackgroundService2>>().await.unwrap();
    }
}

async fn _() {
    // let mut app = Application::new().await;

    app.register_startup::<TestStartup>().await.unwrap();
}

启动应用程序

async fn _() {
    // let mut app = Application::new().await;
    app.run().await.unwrap();
}

你可以控制启动和停止超时(默认每个服务 5 秒)

async fn _() {
    // let mut app = Application::new().await;

    let core_config = app.root_ioc_context.resolve::<Arc<RwLock<CoreConfig>>>().await.unwrap();

    core_config.write().await.on_start_timeout = Duration::from_millis(6000);
    core_config.write().await.on_stop_timeout = Duration::from_millis(6000);
}

目前实现了 CtrlCLifeTimeManagerInnerStateLifeTimeManager

  • 使用 CtrlCLifeTimeManager 在按 ctrl+c 时关闭应用程序
  • 使用 InnerStateLifeTimeManager 仅通过服务请求关闭应用程序

默认的生命周期管理器是 CtrlCLifeTimeManager

你可以自定义应用程序的生命周期管理

pub struct InnerStateLifeTimeManager {
    is_running: AtomicBool,
}

#[async_trait]
impl ILifeTimeManager for CtrlCLifeTimeManager {
    async fn stop(&self) {
        self.is_running.store(false, Ordering::SeqCst)
    }
    
    async fn is_running(&self) -> bool {
        self.is_running.load(Ordering::SeqCst)
    }

    async fn wait_for_stop(&self) {
        while self.is_running.load(Ordering::SeqCst) {
            yield_now().await;
        }
    }
}

async fn _() {
    // let mut app = Application::new().await;

    // Use here you LifeTimeManager
    app.register_life_time_manager::<CtrlCLifeTimeManager>().await.unwrap();
}

示例

use anthill_service_system::{configs::CoreConfig, Application, IStartup, life_time::{ILifeTimeManager, InnerStateLifeTimeManager}};
use std::sync::Arc;

use anthill_di::{
    DependencyContext,
    Constructor,
    types::BuildDependencyResult,
};
use async_trait::async_trait;
use tokio::sync::oneshot;
use tokio::{
    sync::{
        RwLock,
        oneshot::{
            Sender,
            Receiver,
        }
    },
};

use crate::services::IBackgroundService;

struct TestBackgroundService1 {
    ctx: DependencyContext,
}

#[async_trait]
impl Constructor for TestBackgroundService1 {
    async fn ctor(ctx: DependencyContext) -> BuildDependencyResult<Self> {
        Ok(Self { ctx })
    }
}

#[async_trait]
impl IBackgroundService for TestBackgroundService1 {
    async fn execute(&self) {
        let sender = self.ctx.resolve::<Arc<RwLock<Option<Sender<String>>>>>().await.unwrap()
            .write().await
            .take().unwrap();
        sender.send("test".to_string()).unwrap();
    }
}

struct TestBackgroundService2 {
    application_life_time: Arc<dyn ILifeTimeManager>,
    ctx: DependencyContext,
}

#[async_trait]
impl Constructor for TestBackgroundService2 {
    async fn ctor(ctx: DependencyContext) -> BuildDependencyResult<Self> {
        let application_life_time = ctx.resolve().await?;

        Ok(Self {
            application_life_time,
            ctx,
        })
    }
}

#[async_trait]
impl IBackgroundService for TestBackgroundService2 {
    async fn execute(&self) {
        let receiver = self.ctx.resolve::<Arc<RwLock<Option<Receiver<String>>>>>().await.unwrap().write().await.take().unwrap();
        assert_eq!("test".to_string(), receiver.await.unwrap());
        self.application_life_time.stop().await;
    }
}

struct TestStartup {}

#[async_trait]
impl Constructor for TestStartup {
    async fn ctor(_ctx: DependencyContext) -> BuildDependencyResult<Self> {
        Ok(Self {})
    }
}

#[async_trait]
impl IStartup for TestStartup {
async fn configure_dependency(&mut self, root_ioc_context: &mut DependencyContext) {
        let (tx, rx) = oneshot::channel::<String>();
        
        root_ioc_context.register_instance(RwLock::new(Some(tx))).await.unwrap();
        root_ioc_context.register_instance(RwLock::new(Some(rx))).await.unwrap();
    }

    async fn configure_application(&mut self, _ : Arc<RwLock<CoreConfig>>, app: &mut Application) {
        app.register_life_time_manager::<InnerStateLifeTimeManager>().await.unwrap();

        app.register_background_service::<TestBackgroundService1>().await.unwrap();
        app.register_background_service::<TestBackgroundService2>().await.unwrap();
    }
}

#[tokio::main]
async fn main() {
    let mut app = Application::new().await;
  
    app.register_startup::<TestStartup>().await.unwrap();
    
    app.run().await.unwrap();
}

引用

依赖项

~6–15MB
~191K SLoC