Repository: lapce/lapce
File: lapce-data/src/config.rs (Rust)

Code before:
        }
    }
}

pub struct ConfigWatcher {
    config_change_tx: Sender<()>,
}

impl ConfigWatcher {
    pub fn new(event_sink: ExtEventSink) -> (Self, Sender<()>) {
        let (config_finish_tx, config_finish_rx) = bounded::<()>(1);
        let (config_change_tx, config_change_rx) = bounded::<()>(2);

        std::thread::spawn(move || {
            for _ in config_change_rx {
                let event_sink = event_sink.clone();
                let _ = event_sink.submit_command(
                    LAPCE_UI_COMMAND,
                    LapceUICommand::ReloadConfig,
                    Target::Auto,
                );
                // Sleep is necessary here because reloading config is way faster than downloading plugins
                // Thus downloading plugins will constantly flood the channel with messages.
                std::thread::sleep(std::time::Duration::from_secs(1));
                // Don't open the channel again until changes are fully handled
                config_finish_rx.recv().unwrap();
            }
        });
        (Self { config_change_tx }, config_finish_tx)
    }
}

impl notify::EventHandler for ConfigWatcher {
    fn handle_event(&mut self, event: notify::Result<notify::Event>) {
        if let Ok(event) = event {
            match event.kind {
                notify::EventKind::Create(_)
                | notify::EventKind::Modify(_)
                | notify::EventKind::Remove(_) => {
                    // If we fail to send, that means someone else already triggered the job
                    // Don't unwrap because the channel will return an error on full instead of an Option<T>
                    let _ = self.config_change_tx.try_send(());
                }
                _ => {}
            }
        }
    }
}

impl LapceConfig {
    pub fn load(workspace: &LapceWorkspace, disabled_volts: &[VoltID]) -> Self {

Review comment (suggestion):
Do you think this might be a simpler solution? 
```
                    static WAITING: AtomicBool = AtomicBool::new(false);
                    if WAITING.load(std::sync::atomic::Ordering::Acquire) {
                        // still waiting for the config reload timeout, don't do anything
                        return;
                    }
                    WAITING.store(true, std::sync::atomic::Ordering::Release);
                    let event_sink = self.event_sink.clone();
                    std::thread::spawn(move || {
                        std::thread::sleep(std::time::Duration::from_millis(500));
                        WAITING.store(false, std::sync::atomic::Ordering::Release);
                        let _ = event_sink.submit_command(
                            LAPCE_UI_COMMAND,
                            LapceUICommand::ReloadConfig,
                            Target::Auto,
                        );
                    });
```

Code after:
    }
}

pub struct ConfigWatcher {
    event_sink: ExtEventSink,
    delay_handler: Arc<AtomicBool>,
}

impl ConfigWatcher {
    pub fn new(event_sink: ExtEventSink) -> Self {
        Self {
            event_sink,
            delay_handler: Arc::new(AtomicBool::new(false)),
        }
    }
}

impl notify::EventHandler for ConfigWatcher {
    fn handle_event(&mut self, event: notify::Result<notify::Event>) {
        if let Ok(event) = event {
            match event.kind {
                notify::EventKind::Create(_)
                | notify::EventKind::Modify(_)
                | notify::EventKind::Remove(_) => {
                    if self
                        .delay_handler
                        .compare_exchange(
                            false,
                            true,
                            std::sync::atomic::Ordering::Relaxed,
                            std::sync::atomic::Ordering::Relaxed,
                        )
                        .is_ok()
                    {
                        let config_mutex = self.delay_handler.clone();
                        let event_sink = self.event_sink.clone();
                        std::thread::spawn(move || {
                            std::thread::sleep(std::time::Duration::from_millis(
                                500,
                            ));
                            let _ = event_sink.submit_command(
                                LAPCE_UI_COMMAND,
                                LapceUICommand::ReloadConfig,
                                Target::Auto,
                            );
                            config_mutex
                                .store(false, std::sync::atomic::Ordering::Relaxed);
                        });
                    }
                }
                _ => {}