Skip to main content

grug_ls/server/
helper.rs

1use std::{
2    path::PathBuf,
3    sync::mpsc::{Receiver, Sender, channel},
4};
5
6use crate::server::{Server, mod_api::ModApi};
7
8use log::error;
9use log::info;
10use log::warn;
11use notify::Watcher;
12
13pub enum ServerUpdate {
14    ModApiChange(ModApi),
15}
16
17struct ServerWorker {
18    mod_api_path: PathBuf,
19    sender: Sender<ServerUpdate>,
20    watcher_recv: Receiver<notify::Result<notify::Event>>,
21}
22
23impl ServerWorker {
24    pub fn new(
25        mod_api_path: PathBuf,
26        sender: Sender<ServerUpdate>,
27        watcher_recv: Receiver<notify::Result<notify::Event>>,
28    ) -> ServerWorker {
29        ServerWorker {
30            mod_api_path,
31            sender,
32            watcher_recv,
33        }
34    }
35
36    pub fn update(&mut self) {
37        let recv = self.watcher_recv.try_recv();
38        if let Ok(notify::Result::Err(err)) = &recv {
39            warn!("What error: {:?}", err);
40        }
41
42        if let Ok(Ok(event)) = recv {
43            if let notify::EventKind::Access(_) = event.kind {
44            } else {
45                if let Ok(json) = std::fs::read_to_string(&self.mod_api_path) {
46                    let mod_api: Result<ModApi, serde_json::Error> = serde_json::from_str(&json);
47
48                    match mod_api {
49                        Ok(mod_api) => {
50                            info!("Sending new mod_api: {:?}", mod_api);
51                            self.sender
52                                .send(ServerUpdate::ModApiChange(mod_api))
53                                .unwrap();
54                        }
55                        Err(err) => {
56                            error!("Error deserializing mod_api: {:?}", err);
57                        }
58                    }
59                }
60            }
61        }
62    }
63}
64
65pub fn spawn_worker(root_path: PathBuf) -> Option<Receiver<ServerUpdate>> {
66    let (send, recv) = channel::<ServerUpdate>();
67
68    let (watch_send, watch_recv) = channel::<notify::Result<notify::Event>>();
69    let mut watcher = notify::recommended_watcher(watch_send).ok()?;
70
71    std::thread::spawn(move || {
72        let mut worker = ServerWorker::new(root_path.join("mod_api.json"), send, watch_recv);
73
74        info!("Initializing worker main loop");
75        loop {
76            while let notify::Result::Err(_) = watcher.watch(
77                &root_path.join("mod_api.json"),
78                notify::RecursiveMode::NonRecursive,
79            ) {}
80            worker.update();
81        }
82    });
83
84    Some(recv)
85}
86
87impl Server {
88    pub fn handle_worker_messages(&mut self) {
89        if let Ok(message) = self.messages_chan.try_recv() {
90            match message {
91                ServerUpdate::ModApiChange(mod_api) => {
92                    info!("New mod_api: {:?}", mod_api);
93                    self.mod_api = mod_api;
94                }
95            }
96        }
97    }
98}