mirror of
https://github.com/zellij-org/zellij.git
synced 2024-11-22 22:26:54 +03:00
performance(plugins): use a debounced fs watcher (#2546)
* performance(plugins): use a debounced fs watcher * style(fmt): rustfmt * fix(macos): use recommended watcher
This commit is contained in:
parent
317bdfc902
commit
b7436742cd
24
Cargo.lock
generated
24
Cargo.lock
generated
@ -1005,6 +1005,15 @@ dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "file-id"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e13be71e6ca82e91bc0cb862bebaac0b2d1924a5a1d970c822b2f98b63fda8c3"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filedescriptor"
|
||||
version = "0.8.2"
|
||||
@ -1831,6 +1840,19 @@ dependencies = [
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify-debouncer-full"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4812c1eb49be776fb8df4961623bdc01ec9dfdc1abe8211ceb09150a2e64219"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"file-id",
|
||||
"notify",
|
||||
"parking_lot 0.12.1",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.3.7"
|
||||
@ -4424,7 +4446,7 @@ dependencies = [
|
||||
"log4rs",
|
||||
"miette",
|
||||
"nix 0.23.1",
|
||||
"notify",
|
||||
"notify-debouncer-full",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"regex",
|
||||
|
@ -13,7 +13,7 @@ use std::{
|
||||
};
|
||||
use wasmer::{Instance, Module, Store, Value};
|
||||
use zellij_utils::async_std::task::{self, JoinHandle};
|
||||
use zellij_utils::notify::{RecommendedWatcher, Watcher};
|
||||
use zellij_utils::notify_debouncer_full::{notify::RecommendedWatcher, Debouncer, FileIdMap};
|
||||
|
||||
use crate::{
|
||||
background_jobs::BackgroundJob, screen::ScreenInstruction, thread_bus::ThreadSenders,
|
||||
@ -50,7 +50,7 @@ pub struct WasmBridge {
|
||||
loading_plugins: HashMap<(PluginId, RunPlugin), JoinHandle<()>>, // plugin_id to join-handle
|
||||
pending_plugin_reloads: HashSet<RunPlugin>,
|
||||
path_to_default_shell: PathBuf,
|
||||
watcher: Option<RecommendedWatcher>,
|
||||
watcher: Option<Debouncer<RecommendedWatcher, FileIdMap>>,
|
||||
zellij_cwd: PathBuf,
|
||||
capabilities: PluginCapabilities,
|
||||
client_attributes: ClientAttributes,
|
||||
@ -530,7 +530,9 @@ impl WasmBridge {
|
||||
for plugin_id in &plugin_ids {
|
||||
drop(self.unload_plugin(*plugin_id));
|
||||
}
|
||||
drop(self.watcher.as_mut().map(|w| w.unwatch(&self.zellij_cwd)));
|
||||
if let Some(watcher) = self.watcher.take() {
|
||||
watcher.stop_nonblocking();
|
||||
}
|
||||
}
|
||||
fn run_plugin_of_plugin_id(&self, plugin_id: PluginId) -> Option<&RunPlugin> {
|
||||
self.loading_plugins
|
||||
|
@ -3,61 +3,108 @@ use std::path::PathBuf;
|
||||
|
||||
use crate::thread_bus::ThreadSenders;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
|
||||
use zellij_utils::{data::Event, errors::prelude::*};
|
||||
use zellij_utils::notify_debouncer_full::{
|
||||
new_debouncer,
|
||||
notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher},
|
||||
DebounceEventResult, Debouncer, FileIdMap,
|
||||
};
|
||||
use zellij_utils::{data::Event, errors::prelude::Result};
|
||||
|
||||
use zellij_utils::notify::{self, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
|
||||
pub fn watch_filesystem(senders: ThreadSenders, zellij_cwd: &Path) -> Result<RecommendedWatcher> {
|
||||
const DEBOUNCE_DURATION_MS: u64 = 500;
|
||||
|
||||
pub fn watch_filesystem(
|
||||
senders: ThreadSenders,
|
||||
zellij_cwd: &Path,
|
||||
) -> Result<Debouncer<RecommendedWatcher, FileIdMap>> {
|
||||
let path_prefix_in_plugins = PathBuf::from("/host");
|
||||
let current_dir = PathBuf::from(zellij_cwd);
|
||||
let mut watcher = notify::recommended_watcher({
|
||||
move |res: notify::Result<notify::Event>| match res {
|
||||
Ok(event) => {
|
||||
let paths: Vec<PathBuf> = event
|
||||
.paths
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let stripped_prefix_path =
|
||||
p.strip_prefix(¤t_dir).unwrap_or_else(|_| p);
|
||||
path_prefix_in_plugins.join(stripped_prefix_path)
|
||||
let mut debouncer = new_debouncer(
|
||||
Duration::from_millis(DEBOUNCE_DURATION_MS),
|
||||
None,
|
||||
move |result: DebounceEventResult| match result {
|
||||
Ok(events) => {
|
||||
let mut create_events = vec![];
|
||||
let mut read_events = vec![];
|
||||
let mut update_events = vec![];
|
||||
let mut delete_events = vec![];
|
||||
for event in events {
|
||||
match event.kind {
|
||||
EventKind::Access(_) => read_events.push(event),
|
||||
EventKind::Create(_) => create_events.push(event),
|
||||
EventKind::Modify(_) => update_events.push(event),
|
||||
EventKind::Remove(_) => delete_events.push(event),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
let create_paths: Vec<PathBuf> = create_events
|
||||
.drain(..)
|
||||
.map(|e| {
|
||||
e.paths
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let stripped_prefix_path =
|
||||
p.strip_prefix(¤t_dir).unwrap_or_else(|_| p);
|
||||
path_prefix_in_plugins.join(stripped_prefix_path)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
match event.kind {
|
||||
EventKind::Access(_) => {
|
||||
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
|
||||
None,
|
||||
None,
|
||||
Event::FileSystemRead(paths),
|
||||
)]));
|
||||
},
|
||||
EventKind::Create(_) => {
|
||||
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
|
||||
None,
|
||||
None,
|
||||
Event::FileSystemCreate(paths),
|
||||
)]));
|
||||
},
|
||||
EventKind::Modify(_) => {
|
||||
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
|
||||
None,
|
||||
None,
|
||||
Event::FileSystemUpdate(paths),
|
||||
)]));
|
||||
},
|
||||
EventKind::Remove(_) => {
|
||||
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
|
||||
None,
|
||||
None,
|
||||
Event::FileSystemDelete(paths),
|
||||
)]));
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
let read_paths: Vec<PathBuf> = read_events
|
||||
.drain(..)
|
||||
.map(|e| {
|
||||
e.paths
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let stripped_prefix_path =
|
||||
p.strip_prefix(¤t_dir).unwrap_or_else(|_| p);
|
||||
path_prefix_in_plugins.join(stripped_prefix_path)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
let update_paths: Vec<PathBuf> = update_events
|
||||
.drain(..)
|
||||
.map(|e| {
|
||||
e.paths
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let stripped_prefix_path =
|
||||
p.strip_prefix(¤t_dir).unwrap_or_else(|_| p);
|
||||
path_prefix_in_plugins.join(stripped_prefix_path)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
let delete_paths: Vec<PathBuf> = delete_events
|
||||
.drain(..)
|
||||
.map(|e| {
|
||||
e.paths
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let stripped_prefix_path =
|
||||
p.strip_prefix(¤t_dir).unwrap_or_else(|_| p);
|
||||
path_prefix_in_plugins.join(stripped_prefix_path)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![
|
||||
(None, None, Event::FileSystemRead(read_paths)),
|
||||
(None, None, Event::FileSystemCreate(create_paths)),
|
||||
(None, None, Event::FileSystemUpdate(update_paths)),
|
||||
(None, None, Event::FileSystemDelete(delete_paths)),
|
||||
]));
|
||||
},
|
||||
Err(e) => log::error!("watch error: {:?}", e),
|
||||
}
|
||||
})?;
|
||||
Err(errors) => errors
|
||||
.iter()
|
||||
.for_each(|error| log::error!("watch error: {error:?}")),
|
||||
},
|
||||
)?;
|
||||
|
||||
watcher.watch(zellij_cwd, RecursiveMode::Recursive)?;
|
||||
Ok(watcher)
|
||||
debouncer
|
||||
.watcher()
|
||||
.watch(zellij_cwd, RecursiveMode::Recursive)?;
|
||||
Ok(debouncer)
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ tempfile = "3.2.0"
|
||||
kdl = { version = "4.5.0", features = ["span"] }
|
||||
shellexpand = "3.0.0"
|
||||
uuid = { version = "0.8.2", features = ["serde", "v4"] }
|
||||
notify = "6.0.0"
|
||||
async-channel = "1.8.0"
|
||||
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
@ -50,6 +49,7 @@ log4rs = "1.2.0"
|
||||
signal-hook = "0.3"
|
||||
interprocess = "1.2.1"
|
||||
async-std = { version = "1.3.0", features = ["unstable"] }
|
||||
notify-debouncer-full = "0.1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
insta = { version = "1.6.0", features = ["backtrace"] }
|
||||
|
@ -20,6 +20,6 @@ pub mod logging; // Requires log4rs
|
||||
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
pub use ::{
|
||||
anyhow, async_channel, async_std, clap, interprocess, lazy_static, libc, miette, nix, notify,
|
||||
regex, serde, signal_hook, tempfile, termwiz, vte,
|
||||
anyhow, async_channel, async_std, clap, interprocess, lazy_static, libc, miette, nix,
|
||||
notify_debouncer_full, regex, serde, signal_hook, tempfile, termwiz, vte,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user