如何从文件更改中热重载结构

问题描述

我正在尝试在文件更改时进行热重载,但出现此错误: 期望一个实现 Fn trait 的闭包,但这个闭包只实现了 FnMut 这个闭包实现了 FnMut,而不是 Fn

似乎对我从这个库传递给 new_immediate 函数的闭包不满意:

notify = { version = "5.0.0-pre.4",features = ["serde"] }

我的代码:

use announcer::messages::{load_config,save_config,Config,Message};
use notify::{
    event::ModifyKind,Error,Event,EventFn,EventKind,RecommendedWatcher,RecursiveMode,Watcher,};
use tide::{http,Body,Response};

const CONFIG_PATH: &str = "config.json";

#[async_std::main]
async fn main() -> tide::Result<()> {
    let mut config = load_config(CONFIG_PATH).unwrap();

    let mut watcher: RecommendedWatcher =
        Watcher::new_immediate(|result: Result<Event,Error>| {
            let event = result.unwrap();
            
            if event.kind == EventKind::Modify(ModifyKind::Any) {
                config = load_config(CONFIG_PATH).unwrap();
            }
        })?;

    watcher.watch(CONFIG_PATH,RecursiveMode::Recursive)?;

    let mut app = tide::with_state(config);
    app.listen("127.0.0.1:8080").await?;

    Ok(())
}

我在 Rust Discord 初学者聊天中询问,17cupsofcoffee 说我应该使用互斥锁,但我不知道该怎么做。

解决方法

这里的问题是您在另一个线程中生成此监视函数,并且您可能在一个线程中写入它而在另一个线程中读取它,从而导致竞争条件。您应该使用 Mutexlock 来获得一个保护,让您可以从中读取/写入。由于 tide 的全局状态也需要 Clone,因此您还应该将其包装在一个 Arc 中,一个线程安全的引用计数指针:

use announcer::messages::{load_config,save_config,Config,Message};
use notify::{
    event::ModifyKind,Error,Event,EventFn,EventKind,RecommendedWatcher,RecursiveMode,Watcher,};
use tide::{http,Body,Response};
// necessary imports
use std::sync::{Arc,Mutex};

const CONFIG_PATH: &str = "config.json";

#[async_std::main]
async fn main() -> tide::Result<()> {
    // we store it in an Arc<Mutex<T>>
    let config = Arc::new(Mutex::new(load_config(CONFIG_PATH).unwrap()));
    let cloned_config = Arc::clone(&config);

    let mut watcher: RecommendedWatcher =
        Watcher::new_immediate(move |result: Result<Event,Error>| {
            let event = result.unwrap();
            
            if event.kind == EventKind::Modify(ModifyKind::Any) {
                // we lock the mutex to acquire a mutable guard and write to that
                match load_config(CONFIG_PATH) {
                    Ok(new_config) => *cloned_config.lock().unwrap() = new_config,Err(error) => println!("Error reloading config: {:?}",error),}
        })?;

    watcher.watch(CONFIG_PATH,RecursiveMode::Recursive)?;
    
    let mut app = tide::with_state(config);
    app.listen("127.0.0.1:8080").await?;

    Ok(())
}

然后,每当您需要从状态中读取时,您只需锁定互斥锁:

let config_guard = req.state().lock().unwrap();
println!("{:?}",config_guard.foo);

其他参考:

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...