Я пытаюсь выполнить горячую перезагрузку при изменении файла, но получаю эту ошибку: ожидалось закрытие, реализующее черту Fn, но это закрытие реализует только FnMut, это закрытие реализует FnMut, ...

1
Vlady Veselinov 26 Дек 2020 в 17:40

1 ответ

Лучший ответ

Проблема здесь в том, что вы создаете эту функцию наблюдения в другом потоке, и вы можете писать в нее в одном потоке, а читать в другом, вызывая состояние гонки. Вам следует использовать Mutex и { {X1}}, чтобы получить защиту, которая позволяет вам читать / писать в него. Поскольку глобальному состоянию 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);

Для дополнительной информации:

1
Vlady Veselinov 2 Янв 2021 в 14:38