#config-file #hot-reloading #traits #reload #periodic #async #periodically

hot_reload

为 config-file、KVS 等定义周期性热重载和通知器 trait

7 个版本

0.1.6 2024年7月16日
0.1.5 2024年1月23日
0.1.4 2023年7月21日

#358文件系统

Download history 1/week @ 2024-05-01 2/week @ 2024-05-08 43/week @ 2024-05-15 106/week @ 2024-05-22 70/week @ 2024-05-29 91/week @ 2024-06-05 51/week @ 2024-06-12 103/week @ 2024-06-19 28/week @ 2024-06-26 36/week @ 2024-07-03 185/week @ 2024-07-10 153/week @ 2024-07-17 95/week @ 2024-07-24 69/week @ 2024-07-31 10/week @ 2024-08-07 16/week @ 2024-08-14

每月237 次下载

MIT 许可证

10KB
125

为文件、KVS 等提供周期性热重载和通知器

hot_reload hot_reload License: MIT

此库提供 Rust trait 定义和服务库,通过定期检查系统来实现文件、KVS 等的热重载。

Reload Trait 定义

要使用此库,您需要准备自己的 struct 实现 reloader::Reload trait,如下所示

#[async_trait]
/// Trait defining the responsibility of reloaders to periodically load the target value `V` from `Source`.
/// Source could be a file, a KVS, whatever if you can implement `Reload<V>` with `Reload<V>::Source`.
pub trait Reload<V>
where
  V: Eq + PartialEq
{
  type Source;
  async fn new(src: &Self::Source) -> Result<Self, ReloaderError<V>>
  where
    Self: Sized;
  async fn reload(&self) -> Result<Option<V>, ReloaderError<V>>;
}

此 trait 定义了源类型(文件、KVS 等)和重载对象类型 V。以下是一个通过给定文件路径字符串周期性重载配置文件的示例。

pub struct ConfigReloader {
  pub config_path: PathBuf,
}

#[async_trait]
impl Reload<ServerConfig> for ConfigReloader {
  type Source = String;
  async fn new(source: &Self::Source) -> Result<Self, ReloaderError<ServerConfig>> {
    Ok(Self {
      config_path: PathBuf::from(source),
    })
  }

  async fn reload(&self) -> Result<Option<ServerConfig>, ReloaderError<ServerConfig>> {
    let config_str = std::fs::read_to_string(&self.config_path).context("Failed to read config file")?;
    let config: ServerConfig = config_object_from_str(config_str);

    Ok(Some(config))
  }
}

用法

use hot_reload::*;

let (reloader, rx) = ReloaderService::new(source, 10, false).await.unwrap();
tokio::spawn(async move { reloader_service.start().await });
loop {
  tokio::select! {
    // Add main logic of the event loop with up-to-date value
    _ = something.happened() => {
      // ...
    }
    // immediately update if watcher detects the change
    _ = rx.changed()  => {
      if rx.borrow().is_none() {
        break;
      }
      let value = rx.borrow().clone();
      info!("Received value via watcher");
      info!("value: {:?}", value.unwrap().clone());
    }
    else => break
    }
  }
}

依赖项

~2.6–4.5MB
~71K SLoC