working on channel shutdown and caching strategies

This commit is contained in:
alexpasmantier 2024-10-21 23:33:44 +02:00
parent 5556515240
commit 9d6d1f47ba
9 changed files with 60 additions and 42 deletions

View File

@ -1,6 +1,6 @@
use crate::entry::Entry;
use color_eyre::eyre::Result;
use television_derive::{CliChannel, Broadcast, UnitChannel};
use television_derive::{Broadcast, CliChannel, UnitChannel};
mod alias;
pub mod channels;
@ -70,7 +70,7 @@ pub trait OnAir: Send {
/// Check if the channel is currently running.
fn running(&self) -> bool;
/// Turn off
fn shutdown(&self);
}

View File

@ -199,9 +199,7 @@ impl OnAir for Channel {
self.running
}
fn shutdown(&self) {
todo!()
}
fn shutdown(&self) {}
}
#[allow(clippy::unused_async)]

View File

@ -134,7 +134,5 @@ impl OnAir for SelectionChannel {
self.running
}
fn shutdown(&self) {
todo!()
}
fn shutdown(&self) {}
}

View File

@ -161,7 +161,5 @@ impl OnAir for Channel {
self.running
}
fn shutdown(&self) {
todo!()
}
fn shutdown(&self) {}
}

View File

@ -25,6 +25,7 @@ pub struct Channel {
result_count: u32,
total_count: u32,
running: bool,
crawl_handle: tokio::task::JoinHandle<()>,
// PERF: cache results (to make deleting characters smoother) but like
// a shallow cache (maybe more like a stack actually? so we just pop result sets)
}
@ -38,7 +39,7 @@ impl Channel {
1,
);
// start loading files in the background
tokio::spawn(load_files(
let crawl_handle = tokio::spawn(load_files(
starting_dir.to_path_buf(),
matcher.injector(),
));
@ -48,6 +49,7 @@ impl Channel {
result_count: 0,
total_count: 0,
running: false,
crawl_handle,
}
}
@ -133,7 +135,7 @@ impl OnAir for Channel {
}
fn shutdown(&self) {
todo!()
self.crawl_handle.abort();
}
}

View File

@ -1,4 +1,3 @@
use std::sync::Arc;
use color_eyre::owo_colors::OwoColorize;
use devicons::FileIcon;
use ignore::{overrides::OverrideBuilder, DirEntry};
@ -6,7 +5,12 @@ use nucleo::{
pattern::{CaseMatching, Normalization},
Config, Nucleo,
};
use tokio::sync::{oneshot, watch};
use parking_lot::Mutex;
use std::{collections::HashSet, sync::Arc};
use tokio::{
sync::{oneshot, watch},
task::JoinHandle,
};
use tracing::debug;
use crate::{
@ -25,7 +29,10 @@ pub struct Channel {
total_count: u32,
running: bool,
icon: FileIcon,
crawl_cancellation_tx: watch::Sender<bool>,
crawl_handle: JoinHandle<()>,
entry_cache: Arc<Mutex<HashSet<String>>>,
// TODO: implement cache validation/invalidation
cache_valid: bool,
}
impl Channel {
@ -36,12 +43,13 @@ impl Channel {
None,
1,
);
let entry_cache = Arc::new(Mutex::new(HashSet::new()));
// start loading files in the background
let (tx, rx) = watch::channel(false);
tokio::spawn(crawl_for_repos(
// PERF: store the results somewhere in a cache
let crawl_handle = tokio::spawn(crawl_for_repos(
std::env::home_dir().expect("Could not get home directory"),
matcher.injector(),
rx,
entry_cache.clone(),
));
Channel {
matcher,
@ -50,7 +58,9 @@ impl Channel {
total_count: 0,
running: false,
icon: FileIcon::from("git"),
crawl_cancellation_tx: tx,
crawl_handle,
entry_cache,
cache_valid: false,
}
}
@ -137,7 +147,8 @@ impl OnAir for Channel {
}
fn shutdown(&self) {
self.crawl_cancellation_tx.send(true).unwrap();
debug!("Shutting down git repos channel");
self.crawl_handle.abort();
}
}
@ -145,7 +156,7 @@ impl OnAir for Channel {
async fn crawl_for_repos(
starting_point: std::path::PathBuf,
injector: nucleo::Injector<DirEntry>,
cancellation_rx: watch::Receiver<bool>,
entry_cache: Arc<Mutex<HashSet<String>>>,
) {
let mut walker_overrides_builder = OverrideBuilder::new(&starting_point);
walker_overrides_builder.add(".git").unwrap();
@ -158,25 +169,31 @@ async fn crawl_for_repos(
walker.run(|| {
let injector = injector.clone();
let cancellation_rx = cancellation_rx.clone();
let entry_cache = entry_cache.clone();
Box::new(move |result| {
if let Ok(true) = cancellation_rx.has_changed() {
debug!("Crawling for git repos cancelled");
return ignore::WalkState::Quit;
}
if let Ok(entry) = result {
if entry.file_type().unwrap().is_dir()
&& entry.path().ends_with(".git")
{
debug!("Found git repo: {:?}", entry.path());
let _ = injector.push(entry, |e, cols| {
cols[0] = e
if entry.file_type().unwrap().is_dir() {
// if the dir is already in cache, skip it
let path = entry.path().to_string_lossy().to_string();
if entry_cache.lock().contains(&path) {
return ignore::WalkState::Skip;
}
// if the entry is a .git directory, add its parent to the list
// of git repos and cache it
if entry.path().ends_with(".git") {
let parent_path = entry
.path()
.parent()
.unwrap()
.to_string_lossy()
.into();
});
.to_string();
debug!("Found git repo: {:?}", parent_path);
let _ = injector.push(entry, |_e, cols| {
cols[0] = parent_path.clone().into();
});
entry_cache.lock().insert(parent_path);
return ignore::WalkState::Skip;
}
}
}
ignore::WalkState::Continue

View File

@ -150,7 +150,5 @@ impl OnAir for Channel {
self.running
}
fn shutdown(&self) {
todo!()
}
fn shutdown(&self) {}
}

View File

@ -47,13 +47,14 @@ pub struct Channel {
result_count: u32,
total_count: u32,
running: bool,
crawl_handle: tokio::task::JoinHandle<()>,
}
impl Channel {
pub fn new(working_dir: &Path) -> Self {
let matcher = Nucleo::new(Config::DEFAULT, Arc::new(|| {}), None, 1);
// start loading files in the background
tokio::spawn(load_candidates(
let crawl_handle = tokio::spawn(load_candidates(
working_dir.to_path_buf(),
matcher.injector(),
));
@ -63,6 +64,7 @@ impl Channel {
result_count: 0,
total_count: 0,
running: false,
crawl_handle,
}
}
@ -160,7 +162,7 @@ impl OnAir for Channel {
}
fn shutdown(&self) {
todo!()
self.crawl_handle.abort();
}
}

View File

@ -107,13 +107,18 @@ impl Television {
self.reset_results_selection();
self.current_pattern = EMPTY_STRING.to_string();
self.input.reset();
self.channel.shutdown();
self.channel = channel;
}
const MAX_BACKUP_RESULTS: u32 = 1000;
fn backup_current_channel(&mut self) {
self.last_channel = Some(UnitChannel::from(&self.channel));
self.last_channel_results =
self.channel.results(self.channel.result_count(), 0);
self.last_channel_results = self.channel.results(
self.channel.result_count().min(Self::MAX_BACKUP_RESULTS),
0,
);
}
fn find(&mut self, pattern: &str) {